Merge pull request 'master' (#92) from Alienjack/AxibugEmuOnline:master into master

Reviewed-on: #92
This commit is contained in:
sin365 2025-01-26 15:05:11 +08:00
commit 62c6854172
7 changed files with 203 additions and 61 deletions

View File

@ -0,0 +1,55 @@
using System;
using System.Diagnostics;
namespace AxiReplay
{
public partial class FrameProfiler
{
private int m_headFrame;
private int m_cacheCount;
private int m_targetFrameRate;
private RingBuffer<double> m_timePoints;
private double m_lastTime;
private Stopwatch sw;
public void InputHead(int headFrame)
{
m_headFrame = headFrame;
var currentTimeMs = GetCurrTime();
if (m_timePoints.Available() == 60)
CalcCacheCount();
m_timePoints.Write(currentTimeMs - m_lastTime);
m_lastTime = currentTimeMs;
}
public void Reset(int targetFrameRate = 60)
{
if (sw != null) sw.Stop();
sw = Stopwatch.StartNew();
m_timePoints = new RingBuffer<double>(targetFrameRate);
m_lastTime = 0;
m_targetFrameRate = targetFrameRate;
}
void CalcCacheCount()
{
double deltaMax = 0;
while (m_timePoints.TryRead(out double delta))
{
deltaMax = Math.Max(deltaMax, delta);
}
int minCacheCount = (int)Math.Ceiling(deltaMax * m_targetFrameRate);
m_cacheCount = minCacheCount;
}
double GetCurrTime()
{
if (sw == null) return 0;
return sw.Elapsed.TotalMilliseconds;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: cfd4511a83ff0bf4ea7615b87e7d09aa

View File

@ -0,0 +1,78 @@
using System.Threading;
namespace AxiReplay
{
public partial class FrameProfiler
{
internal class RingBuffer<T>
{
private readonly T[] buffer;
private readonly int capacity;
private int writePos;
private int readPos;
private int count;
public RingBuffer(int capacity)
{
this.capacity = capacity;
this.buffer = new T[capacity];
this.writePos = 0;
this.readPos = 0;
this.count = 0;
}
public void Write(T item)
{
int localWritePos;
int localReadPos;
do
{
localWritePos = Volatile.Read(ref writePos);
localReadPos = Volatile.Read(ref readPos);
int nextWritePos = (localWritePos + 1) % capacity;
if (nextWritePos == localReadPos)
{
// 缓冲区已满,覆盖最旧的未读数据
Interlocked.CompareExchange(ref readPos, (localReadPos + 1) % capacity, localReadPos);
}
}
while (Interlocked.CompareExchange(ref writePos, (localWritePos + 1) % capacity, localWritePos) != localWritePos);
buffer[localWritePos] = item;
Interlocked.Increment(ref count);
}
public bool TryRead(out T item)
{
item = default(T);
int localReadPos;
int localWritePos;
do
{
localReadPos = Volatile.Read(ref readPos);
localWritePos = Volatile.Read(ref writePos);
if (localReadPos == localWritePos)
{
return false; // 缓冲区为空
}
}
while (Interlocked.CompareExchange(ref readPos, (localReadPos + 1) % capacity, localReadPos) != localReadPos);
item = buffer[localReadPos];
Interlocked.Decrement(ref count);
return true;
}
public int Available()
{
return Volatile.Read(ref count);
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b17d83b69bd47094594c32fcff9715f4

View File

@ -34,6 +34,8 @@ namespace AxiReplay
/// </summary> /// </summary>
ReplayStep mNextReplay; ReplayStep mNextReplay;
FrameProfiler frameProfiler = new FrameProfiler();
bool bNetInit = false; bool bNetInit = false;
public NetReplay() public NetReplay()
{ {
@ -45,6 +47,8 @@ namespace AxiReplay
mCurrReplay = default(ReplayStep); mCurrReplay = default(ReplayStep);
mCurrReplay.FrameStartID = int.MinValue; mCurrReplay.FrameStartID = int.MinValue;
bNetInit = false; bNetInit = false;
frameProfiler.Reset();
} }
public void InData(ReplayStep inputData, int ServerFrameIdx, uint ServerForwardCount) public void InData(ReplayStep inputData, int ServerFrameIdx, uint ServerForwardCount)
{ {
@ -57,7 +61,10 @@ namespace AxiReplay
bNetInit = true; bNetInit = true;
mNextReplay = mNetReplayQueue.Dequeue(); mNextReplay = mNetReplayQueue.Dequeue();
} }
frameProfiler.InputHead(inputData.FrameStartID);
} }
public bool TryGetNextFrame(out ReplayStep data, out int frameDiff, out bool inputDiff) public bool TryGetNextFrame(out ReplayStep data, out int frameDiff, out bool inputDiff)
{ {
if (!bNetInit) if (!bNetInit)
@ -93,13 +100,15 @@ namespace AxiReplay
{ {
bool result; bool result;
inputDiff = false; inputDiff = false;
//if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count > 0) //if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count > 0)
if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count >= mRemoteForwardCount) if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count >= mRemoteForwardCount)
{ {
//当前帧追加 //当前帧追加
mCurrClientFrameIdx = targetFrame; mCurrClientFrameIdx = targetFrame;
ulong oldInput = mCurrReplay.InPut; ulong oldInput = mCurrReplay.InPut;
mCurrReplay = mNextReplay; mCurrReplay = mNextReplay;
if (oldInput != mCurrReplay.InPut) if (oldInput != mCurrReplay.InPut)
inputDiff = true; inputDiff = true;
mNextReplay = mNetReplayQueue.Dequeue(); mNextReplay = mNetReplayQueue.Dequeue();

View File

@ -47,7 +47,7 @@ public class UMAME : MonoBehaviour, IEmuCore
//设为60帧 //设为60帧
Application.targetFrameRate = 120; Application.targetFrameRate = 60;
// 强制横屏 // 强制横屏
Screen.orientation = ScreenOrientation.LandscapeLeft; Screen.orientation = ScreenOrientation.LandscapeLeft;
instance = this; instance = this;

View File

@ -331,7 +331,6 @@ namespace AxibugEmuOnline.Client.Manager
Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, newJoin); Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, newJoin);
} }
bool bChangeSlot = false;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
var oldSlot = oldslotArr[i]; var oldSlot = oldslotArr[i];
@ -344,68 +343,65 @@ namespace AxibugEmuOnline.Client.Manager
oldSlot.PlayerLocalJoyIdx != newSlot.PlayerLocalJoyIdx oldSlot.PlayerLocalJoyIdx != newSlot.PlayerLocalJoyIdx
) )
{ {
bChangeSlot = true;
if (newSlot.PlayerUID > 0) if (newSlot.PlayerUID > 0)
{ {
OverlayManager.PopTip($"[{newSlot.PlayerNickName}]使用:P{i}"); OverlayManager.PopTip($"[{newSlot.PlayerNickName}]使用:P{i}");
} }
} }
} }
if (bChangeSlot) Eventer.Instance.PostEvent(EEvent.OnRoomSlotDataChanged);
{
Eventer.Instance.PostEvent(EEvent.OnRoomSlotDataChanged);
} //for (int i = 0; i < 4; i++)
//{
//for (int i = 0; i < 4; i++) // long OldPlayer = oldRoomPlayer[i];
//{ // long NewPlayer = newRoomPlayer[i];
// long OldPlayer = oldRoomPlayer[i]; // if (OldPlayer == NewPlayer)
// long NewPlayer = newRoomPlayer[i]; // continue;
// if (OldPlayer == NewPlayer)
// continue; // //位置之前有人,但是离开了
// if (OldPlayer > 0)
// //位置之前有人,但是离开了 // {
// if (OldPlayer > 0) // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, i, OldPlayer);
// { // UserDataBase oldplayer = App.user.GetUserByUid(OldPlayer);
// Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, i, OldPlayer); // string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player";
// UserDataBase oldplayer = App.user.GetUserByUid(OldPlayer); // OverlayManager.PopTip($"[{oldPlayName}]离开房间,手柄位:P{i}");
// string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player"; // if (NewPlayer > 0)//而且害换了一个玩家
// OverlayManager.PopTip($"[{oldPlayName}]离开房间,手柄位:P{i}"); // {
// if (NewPlayer > 0)//而且害换了一个玩家 // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer);
// { // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName);
// Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}");
// mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); // }
// OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); // }
// } // else //之前没人
// } // {
// else //之前没人 // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer);
// { // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName);
// Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}");
// mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); // }
// OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}");
// } // //位置之前有人,但是离开了
// if (OldPlayer > 0)
// //位置之前有人,但是离开了 // {
// if (OldPlayer > 0) // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, i, OldPlayer);
// { // UserDataBase oldplayer = App.user.GetUserByUid(OldPlayer);
// Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, i, OldPlayer); // string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player";
// UserDataBase oldplayer = App.user.GetUserByUid(OldPlayer); // OverlayManager.PopTip($"[{oldPlayName}]离开房间,手柄位:P{i}");
// string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player"; // if (NewPlayer > 0)//而且害换了一个玩家
// OverlayManager.PopTip($"[{oldPlayName}]离开房间,手柄位:P{i}"); // {
// if (NewPlayer > 0)//而且害换了一个玩家 // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer);
// { // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName);
// Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}");
// mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); // }
// OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); // }
// } // else //之前没人
// } // {
// else //之前没人 // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer);
// { // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName);
// Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}");
// mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); // }
// OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); //}
// }
//}
} }
/// <summary> /// <summary>