diff --git a/IReplayReader.cs b/IReplayReader.cs new file mode 100644 index 0000000..c0761a5 --- /dev/null +++ b/IReplayReader.cs @@ -0,0 +1,11 @@ +using System; + +namespace AxiReplay +{ + internal interface IReplayReader : IDisposable + { + bool NextFrame(out ReplayStep data); + bool TakeFrame(int addFrame, out ReplayStep data); + bool NextFramebyFrameIdx(int FrameID, out ReplayStep data); + } +} diff --git a/IReplayWriter.cs b/IReplayWriter.cs new file mode 100644 index 0000000..8f11a28 --- /dev/null +++ b/IReplayWriter.cs @@ -0,0 +1,12 @@ +using System; + +namespace AxiReplay +{ + internal interface IReplayWriter : IDisposable + { + void NextFrame(UInt64 frameInput); + void NextFramebyFrameIdx(int FrameID, UInt64 frameInput); + void TakeFrame(int addFrame, UInt64 frameInput); + void SaveData(string path, bool bNeedDump = false, string dumpFilePath = null); + } +} diff --git a/NetReplay.cs b/NetReplay.cs new file mode 100644 index 0000000..5b7d26e --- /dev/null +++ b/NetReplay.cs @@ -0,0 +1,147 @@ +using System.Collections.Generic; + +namespace AxiReplay +{ + public class NetReplay + { + /// + /// 客户端当前帧 + /// + public int mCurrClientFrameIdx = 0; + /// + /// 服务器远端当前帧 + /// + public int mRemoteFrameIdx { get; private set; } + /// + /// 服务器远端当前提前量 + /// + public int mRemoteForwardCount { get; private set; } + /// + /// Remote 2 Client Frame Gap + /// + public int mDiffFrameCount => mRemoteFrameIdx - mCurrClientFrameIdx; + /// + /// 网络数据队列 + /// + Queue mNetReplayQueue = new Queue(); + /// + /// 当前数据 + /// + ReplayStep mCurrReplay; + /// + /// 下一个数据数据 + /// + ReplayStep mNextReplay; + + bool bNetInit = false; + public NetReplay() + { + ResetData(); + } + public void ResetData() + { + mNetReplayQueue.Clear(); + mCurrReplay = default(ReplayStep); + mCurrReplay.FrameStartID = int.MinValue; + bNetInit = false; + } + public void InData(ReplayStep inputData, int ServerFrameIdx) + { + mNetReplayQueue.Enqueue(inputData); + mRemoteFrameIdx = inputData.FrameStartID; + if (!bNetInit) + { + bNetInit = true; + mNextReplay = mNetReplayQueue.Dequeue(); + } + } + public bool TryGetNextFrame(out ReplayStep data, out int frameDiff, out bool inputDiff) + { + if (!bNetInit) + { + data = default(ReplayStep); + frameDiff = default(int); + inputDiff = false; + return false; + } + TakeFrame(1, out data, out frameDiff, out inputDiff); + return frameDiff > 0; + } + + public bool TryGetNextFrame(int targetFrame, out ReplayStep data, out int frameDiff, out bool inputDiff) + { + if (!bNetInit) + { + data = default(ReplayStep); + frameDiff = default(int); + inputDiff = false; + return false; + } + return TakeFrameToTargetFrame(targetFrame, out data, out frameDiff, out inputDiff); + } + + void TakeFrame(int addFrame, out ReplayStep data, out int bFrameDiff, out bool inputDiff) + { + int targetFrame = mCurrClientFrameIdx + addFrame; + TakeFrameToTargetFrame(targetFrame, out data, out bFrameDiff, out inputDiff); + } + + bool TakeFrameToTargetFrame(int targetFrame, out ReplayStep data, out int bFrameDiff, out bool inputDiff) + { + bool result; + inputDiff = false; + if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count > 0) + { + //当前帧追加 + mCurrClientFrameIdx = targetFrame; + ulong oldInput = mCurrReplay.InPut; + mCurrReplay = mNextReplay; + if (oldInput != mCurrReplay.InPut) + inputDiff = true; + mNextReplay = mNetReplayQueue.Dequeue(); + result = true; + } + else + result = false; + + bFrameDiff = mRemoteFrameIdx - mCurrClientFrameIdx; + data = mCurrReplay; + + return result; + } + + public int GetSkipFrameCount() + { + if(!bNetInit) + return 0; + //本地队列差异高于服务器提前量的值 + int moreNum = mDiffFrameCount - mRemoteForwardCount; + //if (mDiffFrameCount < 0 || mDiffFrameCount > 10000) + // return 0; + + ////游戏刚开始的一小段时间,直接追满 + //if (mCurrClientFrameIdx < 60) + // return moreNum; + + int skip = 0; + if (mDiffFrameCount > short.MaxValue) skip = 0; + else if (moreNum <= 1) skip = 0; + else if (moreNum <= 3) skip = 2; + else if (moreNum <= 6) skip = 2; + else if (moreNum <= 20) skip = moreNum / 2; //20帧以内,平滑跳帧数 + else skip = moreNum;//完全追上 + return skip; + + //var frameGap = mDiffFrameCount; + //if (frameGap > 10000) return 0; + //if (frameGap <= 2) skip = 0; + //if (frameGap > 2 && frameGap < 6) skip = 1 + 1; + //else if (frameGap > 7 && frameGap < 12) skip = 2 + 1; + //else if (frameGap > 13 && frameGap < 20) skip = 3 + 1; + //else skip = frameGap - 2; + + + //return skip; + } + } +} diff --git a/ReplayData.cs b/ReplayData.cs index ab3dd58..c958f2d 100644 --- a/ReplayData.cs +++ b/ReplayData.cs @@ -4,7 +4,7 @@ using System.Text; namespace AxiReplay { - [StructLayout(LayoutKind.Explicit,Size = 44)] + [StructLayout(LayoutKind.Explicit, Size = 44)] public struct ReplayHandler { [FieldOffset(0)] @@ -51,7 +51,7 @@ namespace AxiReplay FM32IP32, FM32IP64, } - public static void GetStringByteData(string str,out byte[] data,out int lenghtWithEnd,Encoding encoding) + public static void GetStringByteData(string str, out byte[] data, out int lenghtWithEnd, Encoding encoding) { data = encoding.GetBytes(str); lenghtWithEnd = data.Length + 1; diff --git a/ReplayReader.cs b/ReplayReader.cs index 7410eb7..e7d3c99 100644 --- a/ReplayReader.cs +++ b/ReplayReader.cs @@ -6,7 +6,7 @@ using static AxiReplay.ReplayData; namespace AxiReplay { - public class ReplayReader : IDisposable + public class ReplayReader : IReplayReader { public ReplayData.ReplayFormat mFormat { get; private set; } public Encoding TexEncoding { get; private set; } @@ -21,10 +21,10 @@ namespace AxiReplay FileStream mStream; BinaryReader mBinaryReader; - int mCurrFrame = -1; + int mCurrFrame = 0; byte[] mNextOutbytes; - ReplayStep currStep; - ReplayStep nextStep; + public ReplayStep currStep; + public ReplayStep nextStep; bool bEnd; List dbgList = new List(); @@ -79,11 +79,12 @@ namespace AxiReplay } } - + void UpdateNextFrame(int targetFrame) { + int LastNextFrameStartID = nextStep.FrameStartID; //如果已经超过 - while (targetFrame > nextStep.FrameStartID) + while (targetFrame >= nextStep.FrameStartID) { if (nextStep.FrameStartID >= handler.AllFrame) { @@ -117,34 +118,31 @@ namespace AxiReplay } dbgList.Add($"{nextStep.FrameStartID} | {nextStep.InPut}"); + //如果这次的NextStep1只推进了1帧,则跳过,交给下一帧判断 + if (nextStep.FrameStartID - LastNextFrameStartID == 1) + { + break; + } + targetFrame++; } } int byFrameIdx = 0; - /// - /// 往前推进帧的,指定帧下标 - /// - public bool NextFramebyFrameIdx(int FrameID,out ReplayStep data) - { - bool res = TakeFrame(FrameID - byFrameIdx, out data); - byFrameIdx = FrameID; - return res; - } /// /// 往前推进1帧的Input(返回是否变化) /// public bool NextFrame(out ReplayStep data) { - return TakeFrame(1,out data); + return TakeFrame(1, out data); } /// /// 往前推进指定帧数量的Input (返回是否变化) /// /// - public bool TakeFrame(int addFrame,out ReplayStep data) + public bool TakeFrame(int addFrame, out ReplayStep data) { bool Changed = false; mCurrFrame += addFrame; @@ -162,6 +160,23 @@ namespace AxiReplay return Changed; } + int lastTest = 0; + /// + /// 往前推进帧的,指定帧下标 + /// + public bool NextFramebyFrameIdx(int FrameID, out ReplayStep data) + { + lastTest = FrameID; + + if (FrameID == 3360) + { + + } + bool res = TakeFrame(FrameID - byFrameIdx, out data); + byFrameIdx = FrameID; + return res; + } + public void Dispose() { mStream.Dispose(); diff --git a/ReplayWriter.cs b/ReplayWriter.cs index 3d0f516..144c889 100644 --- a/ReplayWriter.cs +++ b/ReplayWriter.cs @@ -5,152 +5,155 @@ using System.Text; namespace AxiReplay { - public class ReplayWriter : IDisposable - { - public ReplayData.ReplayFormat mFormat { get; private set; } - public Encoding TexEncoding { get; private set; } - ReplayHandler handler; - string mTitle; - string mNote; - int mAllFrame; - int mAllTime; - long mData; - int mSingleInputLenght; - int mSingleDataLenght; - MemoryStream mStream; - BinaryWriter mBinaryWriter; + public class ReplayWriter : IReplayWriter + { + public ReplayData.ReplayFormat mFormat { get; private set; } + public Encoding TexEncoding { get; private set; } + ReplayHandler handler; + string mTitle; + string mNote; + int mAllFrame; + int mAllTime; + long mData; + int mSingleInputLenght; + int mSingleDataLenght; + MemoryStream mStream; + BinaryWriter mBinaryWriter; - int mCurrFrame; - UInt64 mCurrInput; - ReplayStep wirteStep; + int mCurrFrame; + UInt64 mCurrInput; + ReplayStep wirteStep; - List dbgList = new List(); + List dbgList = new List(); - public ReplayWriter(string Title, string Note, ReplayData.ReplayFormat format, Encoding encoding) - { - mTitle = Title; - mNote = Note; - TexEncoding = encoding; - mFormat = format; - switch (mFormat) - { - case ReplayData.ReplayFormat.FM32IP64: mSingleInputLenght = sizeof(UInt64); break; - case ReplayData.ReplayFormat.FM32IP32: mSingleInputLenght = sizeof(UInt32); break; - case ReplayData.ReplayFormat.FM32IP16: mSingleInputLenght = sizeof(UInt16); break; - case ReplayData.ReplayFormat.FM32IPBYTE: mSingleInputLenght = sizeof(byte); break; - } - mSingleDataLenght = (sizeof(UInt32)) + mSingleInputLenght; + public ReplayWriter(string Title, string Note, ReplayData.ReplayFormat format, Encoding encoding) + { + mTitle = Title; + mNote = Note; + TexEncoding = encoding; + mFormat = format; + switch (mFormat) + { + case ReplayData.ReplayFormat.FM32IP64: mSingleInputLenght = sizeof(UInt64); break; + case ReplayData.ReplayFormat.FM32IP32: mSingleInputLenght = sizeof(UInt32); break; + case ReplayData.ReplayFormat.FM32IP16: mSingleInputLenght = sizeof(UInt16); break; + case ReplayData.ReplayFormat.FM32IPBYTE: mSingleInputLenght = sizeof(byte); break; + } + mSingleDataLenght = (sizeof(UInt32)) + mSingleInputLenght; - mStream = new MemoryStream(); - mBinaryWriter = new BinaryWriter(mStream); + mStream = new MemoryStream(); + mBinaryWriter = new BinaryWriter(mStream); - mCurrFrame = -1; + //mCurrFrame = -1; + mCurrFrame = 0; mCurrInput = int.MaxValue; - wirteStep = new ReplayStep(); + wirteStep = new ReplayStep(); - dbgList.Clear(); + dbgList.Clear(); - } + } - int byFrameIdx = 0; - /// - /// 往前推进帧的,指定帧下标 - /// - /// - public void NextFramebyFrameIdx(int FrameID,UInt64 frameInput) - { - TakeFrame(FrameID - byFrameIdx, frameInput); - byFrameIdx = FrameID; - } + int byFrameIdx = 0; + /// + /// 往前推进帧的,指定帧下标 + /// + /// + public void NextFramebyFrameIdx(int FrameID, UInt64 frameInput) + { + TakeFrame(FrameID - byFrameIdx, frameInput); + byFrameIdx = FrameID; + } - /// - /// 往前推进1帧的Input - /// - /// - public void NextFrame(UInt64 frameInput) - { - TakeFrame(1, frameInput); - } + /// + /// 往前推进1帧的Input + /// + /// + public void NextFrame(UInt64 frameInput) + { + TakeFrame(1, frameInput); + } - /// - /// 往前推进指定帧数量的Input - /// - /// - public void TakeFrame(int addFrame, UInt64 frameInput) - { - if (addFrame < 0) - { - - } - mCurrFrame += addFrame; - if (mCurrInput == frameInput) - return; - mCurrInput = frameInput; + /// + /// 往前推进指定帧数量的Input + /// + /// + public void TakeFrame(int addFrame, UInt64 frameInput) + { + if (addFrame < 0) + { - wirteStep.FrameStartID = mCurrFrame; - wirteStep.InPut = mCurrInput; - dbgList.Add($"{mCurrFrame} | {mCurrInput}"); + } + mCurrFrame += addFrame; + if (mCurrInput == frameInput) + return; + mCurrInput = frameInput; - switch (mFormat) - { - case ReplayData.ReplayFormat.FM32IP64: - mBinaryWriter.Write(wirteStep.FrameStartID); - mBinaryWriter.Write(wirteStep.InPut); - break; - case ReplayData.ReplayFormat.FM32IP32: - mBinaryWriter.Write(BitConverter.GetBytes(wirteStep.All64Data), 0, 4 + 4); - break; - case ReplayData.ReplayFormat.FM32IP16: - mBinaryWriter.Write(BitConverter.GetBytes(wirteStep.All64Data), 0, 4 + 2); - break; - case ReplayData.ReplayFormat.FM32IPBYTE: - mBinaryWriter.Write(BitConverter.GetBytes(wirteStep.All64Data), 0, 4 + 1); - break; - } - } + wirteStep.FrameStartID = mCurrFrame; + wirteStep.InPut = mCurrInput; + dbgList.Add($"{mCurrFrame} | {mCurrInput}"); - public void SaveData(string path, bool bWithDump = false, string dumppath = null) - { - ReplayData.GetStringByteData(mTitle, out byte[] titleData, out int titleLenghtWithEnd, TexEncoding); - ReplayData.GetStringByteData(mNote, out byte[] noteData, out int noteLenghtWithEnd, TexEncoding); + switch (mFormat) + { + case ReplayData.ReplayFormat.FM32IP64: + mBinaryWriter.Write(wirteStep.FrameStartID); + mBinaryWriter.Write(wirteStep.InPut); + break; + case ReplayData.ReplayFormat.FM32IP32: + mBinaryWriter.Write(BitConverter.GetBytes(wirteStep.All64Data), 0, 4 + 4); + break; + case ReplayData.ReplayFormat.FM32IP16: + mBinaryWriter.Write(BitConverter.GetBytes(wirteStep.All64Data), 0, 4 + 2); + break; + case ReplayData.ReplayFormat.FM32IPBYTE: + mBinaryWriter.Write(BitConverter.GetBytes(wirteStep.All64Data), 0, 4 + 1); + break; + } + } - ReplayHandler handler = new ReplayHandler(); - handler.Format = (int)this.mFormat; - handler.DataOffset = ReplayData.HandlerLenght; - handler.CreateTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - handler.AllFrame = wirteStep.FrameStartID; - handler.SingleLenght = mSingleDataLenght; + public void SaveData(string path, bool bWithDump = false, string dumppath = null) + { + byte[] titleData; int titleLenghtWithEnd; + ReplayData.GetStringByteData(mTitle, out titleData, out titleLenghtWithEnd, TexEncoding); + byte[] noteData; int noteLenghtWithEnd; + ReplayData.GetStringByteData(mNote, out noteData, out noteLenghtWithEnd, TexEncoding); - using (FileStream fs = new FileStream(path, FileMode.Create)) - { - using (BinaryWriter bw = new BinaryWriter(fs)) - { - //写入Handler - bw.Write(ReplayData.GetHandlerData(handler)); - //写入Data - bw.Write(mStream.ToArray()); - } - } + ReplayHandler handler = new ReplayHandler(); + handler.Format = (int)this.mFormat; + handler.DataOffset = ReplayData.HandlerLenght; + handler.CreateTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + handler.AllFrame = wirteStep.FrameStartID; + handler.SingleLenght = mSingleDataLenght; - if (bWithDump) - { - List temp = new List(); - temp.Add($"Format => {handler.Format}"); - temp.Add($"DataOffset => {handler.DataOffset}"); - temp.Add($"CreateTime => {handler.CreateTime}"); - temp.Add($"AllFrame => {handler.AllFrame}"); - temp.Add($"SingleLenght => {handler.SingleLenght}"); - dbgList.InsertRange(0,temp); - File.WriteAllLines(dumppath, dbgList); - } - } + using (FileStream fs = new FileStream(path, FileMode.Create)) + { + using (BinaryWriter bw = new BinaryWriter(fs)) + { + //写入Handler + bw.Write(ReplayData.GetHandlerData(handler)); + //写入Data + bw.Write(mStream.ToArray()); + } + } - public void Dispose() - { - mStream.Dispose(); - mBinaryWriter.Dispose(); - //TODO - } + if (bWithDump) + { + List temp = new List(); + temp.Add($"Format => {handler.Format}"); + temp.Add($"DataOffset => {handler.DataOffset}"); + temp.Add($"CreateTime => {handler.CreateTime}"); + temp.Add($"AllFrame => {handler.AllFrame}"); + temp.Add($"SingleLenght => {handler.SingleLenght}"); + dbgList.InsertRange(0, temp); + File.WriteAllLines(dumppath, dbgList); + } + } - } + public void Dispose() + { + mStream.Dispose(); + mBinaryWriter.Dispose(); + //TODO + } + + } }