服务端跟随新用户槽位 更改管理 ,以及对象池
This commit is contained in:
parent
ff3c511895
commit
5caff2dbda
401
AxibugEmuOnline.Server/Common/ObjectPoolAuto.cs
Normal file
401
AxibugEmuOnline.Server/Common/ObjectPoolAuto.cs
Normal file
@ -0,0 +1,401 @@
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace AxibugEmuOnline.Server
|
||||
{
|
||||
public static class ObjectPoolAuto
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或者创建一个新的
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(T)"/> 需要回收参见这个</remarks>
|
||||
public static T Acquire<T>()
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Acquire();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或者创建一个新的
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(T)"/> 需要回收参见这个</remarks>
|
||||
public static void Acquire<T>(out T item)
|
||||
where T : class, new()
|
||||
=> item = ObjectPool<T>.Acquire();
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象
|
||||
/// </summary>
|
||||
public static void Release<T>(T item)
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Release(item);
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象
|
||||
/// </summary>
|
||||
public static void Release<T>(ref T item) where T : class, new()
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
ObjectPool<T>.Release(item);
|
||||
item = null;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
public const string
|
||||
NotClearError = " They must be cleared before being released to the pool and not modified after that.";
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建List
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(List{T})"/> 回收参见此方法</remarks>
|
||||
public static List<T> AcquireList<T>()
|
||||
{
|
||||
var list = ObjectPool<List<T>>.Acquire();
|
||||
AppSrv.g_Log.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收List
|
||||
/// </summary>
|
||||
public static void Release<T>(List<T> list)
|
||||
{
|
||||
list.Clear();
|
||||
ObjectPool<List<T>>.Release(list);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建Queue
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(Queue{T})"/> 回收参见此方法</remarks>
|
||||
public static Queue<T> AcquireQueue<T>()
|
||||
{
|
||||
var queue = ObjectPool<Queue<T>>.Acquire();
|
||||
AppSrv.g_Log.Assert(queue.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return queue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收Queue
|
||||
/// </summary>
|
||||
public static void Release<T>(Queue<T> list)
|
||||
{
|
||||
list.Clear();
|
||||
ObjectPool<Queue<T>>.Release(list);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建HashSet
|
||||
/// </summary>
|
||||
public static HashSet<T> AcquireSet<T>()
|
||||
{
|
||||
var set = ObjectPool<HashSet<T>>.Acquire();
|
||||
AppSrv.g_Log.Assert(set.Count == 0, "A pooled set is not empty." + NotClearError);
|
||||
return set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放HashSet
|
||||
/// </summary>
|
||||
public static void Release<T>(HashSet<T> set)
|
||||
{
|
||||
set.Clear();
|
||||
ObjectPool<HashSet<T>>.Release(set);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个字符串StringBuilder
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release(StringBuilder)"/>回收参见这个</remarks>
|
||||
public static StringBuilder AcquireStringBuilder()
|
||||
{
|
||||
var builder = ObjectPool<StringBuilder>.Acquire();
|
||||
AppSrv.g_Log.Assert(builder.Length == 0, $"A pooled {nameof(StringBuilder)} is not empty." + NotClearError);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收 StringBuilder
|
||||
/// </summary>
|
||||
public static void Release(StringBuilder builder)
|
||||
{
|
||||
builder.Length = 0;
|
||||
ObjectPool<StringBuilder>.Release(builder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收 StringBuilder
|
||||
/// </summary>
|
||||
public static string ReleaseToString(this StringBuilder builder)
|
||||
{
|
||||
var result = builder.ToString();
|
||||
Release(builder);
|
||||
return result;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static class Cache<T>
|
||||
{
|
||||
public static readonly Dictionary<MethodInfo, KeyValuePair<Func<T>, T>>
|
||||
Results = new Dictionary<MethodInfo, KeyValuePair<Func<T>, T>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 此方法主要用于频繁绘制缓存,比如说GUI绘制
|
||||
/// </summary>
|
||||
public static T GetCachedResult<T>(Func<T> function)
|
||||
{
|
||||
var method = function.Method;
|
||||
if (!Cache<T>.Results.TryGetValue(method, out var result))
|
||||
{
|
||||
|
||||
result = new KeyValuePair<Func<T>, T>(function, function());
|
||||
Cache<T>.Results.Add(method, result);
|
||||
}
|
||||
else if (result.Key != function)
|
||||
{
|
||||
AppSrv.g_Log.Warning(
|
||||
$"{nameof(GetCachedResult)}<{typeof(T).Name}>" +
|
||||
$" was previously called on {method.Name} with a different target." +
|
||||
" This likely means that a new delegate is being passed into every call" +
|
||||
" so it can't actually return the same cached object.");
|
||||
}
|
||||
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
public static class Disposable
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="List{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable Acquire<T>(out T item)
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Disposable.Acquire(out item);
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="List{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable AcquireList<T>(out List<T> list)
|
||||
{
|
||||
var disposable = ObjectPool<List<T>>.Disposable.Acquire(out list, onRelease: (l) => l.Clear());
|
||||
AppSrv.g_Log.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="HashSet{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable AcquireSet<T>(out HashSet<T> set)
|
||||
{
|
||||
var disposable = ObjectPool<HashSet<T>>.Disposable.Acquire(out set, onRelease: (s) => s.Clear());
|
||||
AppSrv.g_Log.Assert(set.Count == 0, "A pooled set is not empty." + NotClearError);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
|
||||
public static class ObjectPool<T> where T : class, new()
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly List<T>
|
||||
Items = new List<T>();
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The number of spare items currently in the pool.</summary>
|
||||
public static int Count
|
||||
{
|
||||
get => Items.Count;
|
||||
set
|
||||
{
|
||||
var count = Items.Count;
|
||||
if (count < value)
|
||||
{
|
||||
if (Items.Capacity < value)
|
||||
Items.Capacity = NextPowerOfTwo(value);
|
||||
|
||||
do
|
||||
{
|
||||
Items.Add(new T());
|
||||
count++;
|
||||
}
|
||||
while (count < value);
|
||||
|
||||
}
|
||||
else if (count > value)
|
||||
{
|
||||
Items.RemoveRange(value, count - value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int NextPowerOfTwo(int value)
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
throw new ArgumentException("Value must be greater than zero.");
|
||||
}
|
||||
|
||||
int powerOfTwo = 1;
|
||||
while (powerOfTwo < value)
|
||||
{
|
||||
powerOfTwo <<= 1; // equivalent to multiplying by 2
|
||||
}
|
||||
|
||||
return powerOfTwo;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="Count"/> is less than the specified value, this method increases it to that value by
|
||||
/// creating new objects.
|
||||
/// </summary>
|
||||
public static void SetMinCount(int count)
|
||||
{
|
||||
if (Count < count)
|
||||
Count = count;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The <see cref="List{T}.Capacity"/> of the internal list of spare items.</summary>
|
||||
public static int Capacity
|
||||
{
|
||||
get => Items.Capacity;
|
||||
set
|
||||
{
|
||||
if (Items.Count > value)
|
||||
Items.RemoveRange(value, Items.Count - value);
|
||||
Items.Capacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Returns a spare item if there are any, or creates a new one.</summary>
|
||||
/// <remarks>Remember to <see cref="Release(T)"/> it when you are done.</remarks>
|
||||
public static T Acquire()
|
||||
{
|
||||
var count = Items.Count;
|
||||
if (count == 0)
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
else
|
||||
{
|
||||
count--;
|
||||
var item = Items[count];
|
||||
Items.RemoveAt(count);
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Adds the `item` to the list of spares so it can be reused.</summary>
|
||||
public static void Release(T item)
|
||||
{
|
||||
Items.Add(item);
|
||||
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Returns a description of the state of this pool.</summary>
|
||||
public static string GetDetails()
|
||||
{
|
||||
return
|
||||
$"{typeof(T).Name}" +
|
||||
$" ({nameof(Count)} = {Items.Count}" +
|
||||
$", {nameof(Capacity)} = {Items.Capacity}" +
|
||||
")";
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="IDisposable"/> system to allow pooled objects to be acquired and released within <c>using</c>
|
||||
/// statements instead of needing to manually release everything.
|
||||
/// </summary>
|
||||
public sealed class Disposable : IDisposable
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly List<Disposable> LazyStack = new List<Disposable>();
|
||||
|
||||
private static int _ActiveDisposables;
|
||||
|
||||
private T _Item;
|
||||
private Action<T> _OnRelease;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private Disposable() { }
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Acquire"/> to set the `item` and returns an <see cref="IDisposable"/>
|
||||
/// that will call <see cref="Release(T)"/> on the `item` when disposed.
|
||||
/// </summary>
|
||||
public static IDisposable Acquire(out T item, Action<T> onRelease = null)
|
||||
{
|
||||
Disposable disposable;
|
||||
|
||||
if (LazyStack.Count <= _ActiveDisposables)
|
||||
{
|
||||
LazyStack.Add(disposable = new Disposable());
|
||||
}
|
||||
else
|
||||
{
|
||||
disposable = LazyStack[_ActiveDisposables];
|
||||
}
|
||||
|
||||
_ActiveDisposables++;
|
||||
|
||||
disposable._Item = item = ObjectPool<T>.Acquire();
|
||||
disposable._OnRelease = onRelease;
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_OnRelease?.Invoke(_Item);
|
||||
Release(_Item);
|
||||
_ActiveDisposables--;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,10 @@ namespace AxibugEmuOnline.Server.Event
|
||||
}
|
||||
else
|
||||
{
|
||||
eventDic.Add(evt, new List<Delegate>() { callback });
|
||||
//eventDic.Add(evt, new List<Delegate>() { callback });
|
||||
List<Delegate> delList = ObjectPoolAuto.AcquireList<Delegate>();
|
||||
delList.Add(callback);
|
||||
eventDic.Add(evt, delList);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -92,7 +95,12 @@ namespace AxibugEmuOnline.Server.Event
|
||||
if (eventDic.ContainsKey(evt))
|
||||
{
|
||||
eventDic[evt].Remove(callback);
|
||||
if (eventDic[evt].Count == 0) eventDic.Remove(evt);
|
||||
if (eventDic[evt].Count == 0)
|
||||
{
|
||||
//eventDic.Remove(evt);
|
||||
ObjectPoolAuto.Release(eventDic[evt]);
|
||||
eventDic.Remove(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
@ -20,12 +20,12 @@ namespace AxibugEmuOnline.Server
|
||||
|
||||
public static void InitServer(int port)
|
||||
{
|
||||
g_Log = new LogManager();
|
||||
Config.LoadConfig();
|
||||
Haoyue_SQLPoolManager.InitConnMgr();
|
||||
g_Tick = new TickManager();
|
||||
g_ClientMgr = new ClientManager();
|
||||
g_ClientMgr.Init(45000, 120);
|
||||
g_Log = new LogManager();
|
||||
g_Login = new LoginManager();
|
||||
g_Chat = new ChatManager();
|
||||
g_UserMgr = new UserManager();
|
||||
|
@ -1,10 +1,8 @@
|
||||
using AxibugEmuOnline.Server.Common;
|
||||
using AxibugEmuOnline.Server.Event;
|
||||
using AxibugEmuOnline.Server.NetWork;
|
||||
using AxibugProtobuf;
|
||||
using MySql.Data.MySqlClient;
|
||||
using System.Net.Sockets;
|
||||
using static AxibugEmuOnline.Server.RoomManager;
|
||||
|
||||
namespace AxibugEmuOnline.Server.Manager
|
||||
{
|
||||
|
@ -1,4 +1,7 @@
|
||||
namespace AxibugEmuOnline.Server.Manager
|
||||
using AxibugProtobuf;
|
||||
using static Mysqlx.Expect.Open.Types;
|
||||
|
||||
namespace AxibugEmuOnline.Server.Manager
|
||||
{
|
||||
public class LogManager
|
||||
{
|
||||
@ -19,6 +22,14 @@
|
||||
//Console.WriteLine(str);
|
||||
}
|
||||
|
||||
public void Assert(bool conditional, string message)
|
||||
{
|
||||
if (!conditional)
|
||||
{
|
||||
Debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void Warning(string str)
|
||||
{
|
||||
Console.WriteLine(str);
|
||||
|
@ -4,6 +4,7 @@ using AxibugEmuOnline.Server.NetWork;
|
||||
using AxibugProtobuf;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
@ -70,6 +71,8 @@ namespace AxibugEmuOnline.Server
|
||||
{
|
||||
if (mDictRoom.ContainsKey(RoomID))
|
||||
{
|
||||
mDictRoom[RoomID].Dispose();
|
||||
|
||||
mDictRoom.Remove(RoomID);
|
||||
mKeyRoomList.Remove(RoomID);
|
||||
}
|
||||
@ -83,16 +86,14 @@ namespace AxibugEmuOnline.Server
|
||||
return data;
|
||||
}
|
||||
|
||||
public List<Data_RoomData> GetRoomList()
|
||||
public void GetRoomList(ref List<Data_RoomData> roomList)
|
||||
{
|
||||
lock (mDictRoom)
|
||||
{
|
||||
List<Data_RoomData> temp = new List<Data_RoomData>();
|
||||
foreach (var room in mDictRoom)
|
||||
{
|
||||
temp.AddRange(mDictRoom.Values);
|
||||
roomList.AddRange(mDictRoom.Values);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,9 +178,11 @@ namespace AxibugEmuOnline.Server
|
||||
Protobuf_Room_List msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_List>(reqData);
|
||||
|
||||
Protobuf_Room_List_RESP resp = new Protobuf_Room_List_RESP();
|
||||
List<Data_RoomData> temp = GetRoomList();
|
||||
List<Data_RoomData> temp = ObjectPoolAuto.AcquireList<Data_RoomData>();
|
||||
GetRoomList(ref temp);
|
||||
foreach (var room in temp)
|
||||
resp.RoomMiniInfoList.Add(GetProtoDataRoom(room));
|
||||
ObjectPoolAuto.Release(temp);
|
||||
AppSrv.g_ClientMgr.ClientSend(_c, (int)CommandID.CmdRoomList, (int)ErrorCode.ErrorOk, ProtoBufHelper.Serizlize(resp));
|
||||
}
|
||||
public void CmdRoomGetScreen(Socket sk, byte[] reqData)
|
||||
@ -513,12 +516,15 @@ namespace AxibugEmuOnline.Server
|
||||
RoomMiniInfo = GetProtoDataRoom(room)
|
||||
};
|
||||
|
||||
List<ClientInfo> userlist = room.GetAllPlayerClientList();
|
||||
List<ClientInfo> userlist = ObjectPoolAuto.AcquireList<ClientInfo>();
|
||||
room.GetAllPlayerClientList(ref userlist);
|
||||
|
||||
foreach (ClientInfo _c in userlist)
|
||||
{
|
||||
AppSrv.g_ClientMgr.ClientSend(_c, (int)CommandID.CmdRoomMyRoomStateChanged, (int)ErrorCode.ErrorOk, ProtoBufHelper.Serizlize(resp));
|
||||
}
|
||||
|
||||
ObjectPoolAuto.Release(userlist);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -527,7 +533,10 @@ namespace AxibugEmuOnline.Server
|
||||
/// <param name="room"></param>
|
||||
public void SendRoomStepChange(Data_RoomData room)
|
||||
{
|
||||
List<ClientInfo> roomClient = room.GetAllPlayerClientList();
|
||||
|
||||
List<ClientInfo> roomClient = ObjectPoolAuto.AcquireList<ClientInfo>();
|
||||
room.GetAllPlayerClientList(ref roomClient);
|
||||
|
||||
switch (room.GameState)
|
||||
{
|
||||
case RoomGameState.WaitRawUpdate:
|
||||
@ -562,6 +571,8 @@ namespace AxibugEmuOnline.Server
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ObjectPoolAuto.Release(roomClient);
|
||||
}
|
||||
|
||||
#region 房间帧循环
|
||||
@ -591,7 +602,7 @@ namespace AxibugEmuOnline.Server
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class Data_RoomData
|
||||
public class Data_RoomData : IDisposable
|
||||
{
|
||||
public int RoomID { get; private set; }
|
||||
public int GameRomID { get; private set; }
|
||||
@ -612,9 +623,13 @@ namespace AxibugEmuOnline.Server
|
||||
public uint mCurrServerFrameId = 0;
|
||||
public ServerInputSnapShot mCurrInputData;
|
||||
public Queue<(uint, ServerInputSnapShot)> mInputQueue;
|
||||
|
||||
public List<double> send2time;
|
||||
const int SynLimitOnSec = 63;
|
||||
|
||||
object synInputLock = new object();
|
||||
//TODO
|
||||
public Dictionary<int, Queue<byte[]>> mDictPlayerIdx2SendQueue;
|
||||
//public Dictionary<int, Queue<byte[]>> mDictPlayerIdx2SendQueue;
|
||||
public RoomGameState GameState
|
||||
{
|
||||
get { return mGameState; }
|
||||
@ -641,6 +656,7 @@ namespace AxibugEmuOnline.Server
|
||||
public uint SrvForwardFrames { get; set; }
|
||||
public void Init(int roomID, int gameRomID, string roomHash, long hostUId, bool bloadState = false)
|
||||
{
|
||||
Dispose();
|
||||
RoomID = roomID;
|
||||
GameRomID = gameRomID;
|
||||
RomHash = roomHash;
|
||||
@ -658,12 +674,39 @@ namespace AxibugEmuOnline.Server
|
||||
PlayerSlot[i].Init(i);
|
||||
|
||||
//PlayerReadyState = new bool[4];
|
||||
SynUIDs = new List<long>();//广播角色列表
|
||||
SynUIDs = ObjectPoolAuto.AcquireList<long>();//new List<long>();//广播角色列表
|
||||
GameState = RoomGameState.NoneGameState;
|
||||
mCurrInputData = new ServerInputSnapShot();
|
||||
mInputQueue = new Queue<(uint, ServerInputSnapShot)>();
|
||||
mDictPlayerIdx2SendQueue = new Dictionary<int, Queue<byte[]>>();
|
||||
mInputQueue = ObjectPoolAuto.AcquireQueue<(uint, ServerInputSnapShot)>();
|
||||
// new Queue<(uint, ServerInputSnapShot)>();
|
||||
//mDictPlayerIdx2SendQueue = new Dictionary<int, Queue<byte[]>>();
|
||||
send2time = ObjectPoolAuto.AcquireList<double>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 房间释放时,需要调用
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (SynUIDs != null)
|
||||
{
|
||||
ObjectPoolAuto.Release(SynUIDs);
|
||||
SynUIDs = null;
|
||||
}
|
||||
|
||||
if (mInputQueue != null)
|
||||
{
|
||||
ObjectPoolAuto.Release(mInputQueue);
|
||||
mInputQueue = null;
|
||||
}
|
||||
|
||||
if (send2time != null)
|
||||
{
|
||||
ObjectPoolAuto.Release(send2time);
|
||||
send2time = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<uint, uint> GetSlotDataByUID(long uid)
|
||||
{
|
||||
Dictionary<uint, uint> slotIdx2JoyIdx = new Dictionary<uint, uint>();
|
||||
@ -736,13 +779,13 @@ namespace AxibugEmuOnline.Server
|
||||
else if (Player2_UID == uid) bHad = true;
|
||||
else if (Player3_UID == uid) bHad = true;
|
||||
else if (Player4_UID == uid) bHad = true;
|
||||
if (bHad)
|
||||
if (!bHad)
|
||||
SynUIDs.RemoveAt(i);
|
||||
}
|
||||
if (!SynUIDs.Contains(Player1_UID)) SynUIDs.Add(Player1_UID);
|
||||
if (!SynUIDs.Contains(Player2_UID)) SynUIDs.Add(Player2_UID);
|
||||
if (!SynUIDs.Contains(Player3_UID)) SynUIDs.Add(Player3_UID);
|
||||
if (!SynUIDs.Contains(Player4_UID)) SynUIDs.Add(Player4_UID);
|
||||
if (Player1_UID > 0 && !SynUIDs.Contains(Player1_UID)) SynUIDs.Add(Player1_UID);
|
||||
if (Player2_UID > 0 && !SynUIDs.Contains(Player2_UID)) SynUIDs.Add(Player2_UID);
|
||||
if (Player3_UID > 0 && !SynUIDs.Contains(Player3_UID)) SynUIDs.Add(Player3_UID);
|
||||
if (Player4_UID > 0 && !SynUIDs.Contains(Player4_UID)) SynUIDs.Add(Player4_UID);
|
||||
}
|
||||
|
||||
#region 准备状态管理
|
||||
@ -790,7 +833,7 @@ namespace AxibugEmuOnline.Server
|
||||
public void SetPlayerSlotData(ClientInfo _c, ref readonly Dictionary<uint, uint> newSlotIdx2JoyIdx)
|
||||
{
|
||||
Dictionary<uint, uint> oldSlotIdx2JoyIdx = GetSlotDataByUID(_c.UID);
|
||||
HashSet<uint> diffSlotIdxs = new HashSet<uint>();
|
||||
HashSet<uint> diffSlotIdxs = ObjectPoolAuto.AcquireSet<uint>();// new HashSet<uint>();
|
||||
foreach (var old in oldSlotIdx2JoyIdx)
|
||||
{
|
||||
uint old_slotIdx = old.Key;
|
||||
@ -830,6 +873,8 @@ namespace AxibugEmuOnline.Server
|
||||
//更新需要同步的UID
|
||||
UpdateSynUIDs();
|
||||
_c.RoomState.SetRoomData(this.RoomID);
|
||||
|
||||
ObjectPoolAuto.Release(diffSlotIdxs);
|
||||
}
|
||||
public void RemovePlayer(ClientInfo _c)
|
||||
{
|
||||
@ -873,9 +918,8 @@ namespace AxibugEmuOnline.Server
|
||||
|
||||
return true;
|
||||
}
|
||||
public List<ClientInfo> GetAllPlayerClientList()
|
||||
public void GetAllPlayerClientList(ref List<ClientInfo> list)
|
||||
{
|
||||
List<ClientInfo> list = new List<ClientInfo>();
|
||||
List<long> Uids = SynUIDs;
|
||||
foreach (long uid in Uids)
|
||||
{
|
||||
@ -883,7 +927,6 @@ namespace AxibugEmuOnline.Server
|
||||
continue;
|
||||
list.Add(_c);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void SetInputBySlotIdxJoyIdx(uint SlotIdx, uint LocalJoyIdx, ServerInputSnapShot clieninput)
|
||||
@ -902,7 +945,10 @@ namespace AxibugEmuOnline.Server
|
||||
}
|
||||
public void UpdateRoomForwardNum()
|
||||
{
|
||||
List<ClientInfo> playerlist = GetAllPlayerClientList();
|
||||
|
||||
List<ClientInfo> playerlist = ObjectPoolAuto.AcquireList<ClientInfo>();
|
||||
GetAllPlayerClientList(ref playerlist);
|
||||
|
||||
double maxNetDelay = 0;
|
||||
for (int i = 0; i < playerlist.Count; i++)
|
||||
{
|
||||
@ -914,13 +960,15 @@ namespace AxibugEmuOnline.Server
|
||||
if (SrvForwardFrames < 2)
|
||||
SrvForwardFrames = 2;
|
||||
//AppSrv.g_Log.Debug($"服务器提前跑帧数:Max(2,({maxNetDelay} / {0.016f}) + {MustTaskFrame}) = {SrvForwardFrames}");
|
||||
|
||||
ObjectPoolAuto.Release(playerlist);
|
||||
}
|
||||
|
||||
#region 帧相关
|
||||
void StartNewTick()
|
||||
{
|
||||
mInputQueue.Clear();
|
||||
mDictPlayerIdx2SendQueue.Clear();
|
||||
//mDictPlayerIdx2SendQueue.Clear();
|
||||
|
||||
mCurrServerFrameId = 0;
|
||||
mCurrInputData.all = 1;
|
||||
@ -951,8 +999,6 @@ namespace AxibugEmuOnline.Server
|
||||
ulong LastTestSend = 0;
|
||||
internal ulong LastTestRecv;
|
||||
|
||||
public List<double> send2time = new List<double>();
|
||||
const int SynLimitOnSec = 63;
|
||||
|
||||
/// <summary>
|
||||
/// 广播数据
|
||||
@ -978,7 +1024,8 @@ namespace AxibugEmuOnline.Server
|
||||
if (!flagInitList)
|
||||
{
|
||||
flagInitList = true;
|
||||
temp = new List<(uint frameId, ServerInputSnapShot inputdata)>();
|
||||
//temp = new List<(uint frameId, ServerInputSnapShot inputdata)>();
|
||||
temp = ObjectPoolAuto.AcquireList<(uint frameId, ServerInputSnapShot inputdata)>();
|
||||
}
|
||||
temp.Add(mInputQueue.Dequeue());
|
||||
send2time.Add(timeNow);
|
||||
@ -1010,6 +1057,8 @@ namespace AxibugEmuOnline.Server
|
||||
// AppSrv.g_Log.Debug($" {DateTime.Now.ToString("hh:mm:ss.fff")} SynInput=> RoomID->{RoomID} ServerFrameID->{mCurrServerFrameId} SynUIDs=>{string.Join(",", SynUIDs)} ");
|
||||
//}
|
||||
}
|
||||
|
||||
ObjectPoolAuto.Release(temp);
|
||||
}
|
||||
|
||||
bool CheckRoomStateChange(int oldPlayerCount, int newPlayerCount)
|
||||
@ -1174,6 +1223,7 @@ namespace AxibugEmuOnline.Server
|
||||
forwaFrame = targetFrame - mCurrServerFrameId;
|
||||
return forwaFrame > 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,10 @@ namespace AxibugEmuOnline.Server.NetWork
|
||||
}
|
||||
else
|
||||
{
|
||||
netEventDic.Add(cmd, new List<Delegate>() { callback });
|
||||
//netEventDic.Add(cmd, new List<Delegate>() { callback });
|
||||
List<Delegate> delList = ObjectPoolAuto.AcquireList<Delegate>();
|
||||
delList.Add(callback);
|
||||
netEventDic.Add(cmd, delList);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -49,7 +52,12 @@ namespace AxibugEmuOnline.Server.NetWork
|
||||
if (netEventDic.ContainsKey(cmd))
|
||||
{
|
||||
netEventDic[cmd].Remove(callback);
|
||||
if (netEventDic[cmd].Count == 0) netEventDic.Remove(cmd);
|
||||
if (netEventDic[cmd].Count == 0)
|
||||
{
|
||||
//netEventDic.Remove(cmd);
|
||||
ObjectPoolAuto.Release(netEventDic[cmd]);
|
||||
netEventDic.Remove(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
@ -21,7 +21,10 @@ namespace AxibugEmuOnline.Server
|
||||
{
|
||||
case "rlist":
|
||||
{
|
||||
var roomlist = AppSrv.g_Room.GetRoomList();
|
||||
|
||||
List<Data_RoomData> roomlist = ObjectPoolAuto.AcquireList<Data_RoomData>();
|
||||
AppSrv.g_Room.GetRoomList(ref roomlist);
|
||||
|
||||
AppSrv.g_Log.Info($"RoomCount:{roomlist.Count}");
|
||||
foreach (var room in roomlist)
|
||||
{
|
||||
@ -55,6 +58,7 @@ namespace AxibugEmuOnline.Server
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectPoolAuto.Release(roomlist);
|
||||
}
|
||||
break;
|
||||
case "list":
|
||||
|
Loading…
Reference in New Issue
Block a user