Merge pull request 'master' (#98) from Alienjack/AxibugEmuOnline:master into master
Reviewed-on: #98
This commit is contained in:
commit
e6ef077f16
AxibugEmuOnline.Client/Assets
Plugins/AxiReplay
Script/AppMain
EmuCore.csEmuCore.cs.meta
Emulator
EssgeeEmulator
MameEmulator
NesEmulator
StoicGooseEmulator
Manager
UI/InGameUI
@ -65,7 +65,7 @@ namespace AxiReplay
|
||||
frameProfiler.InputHead(inputData.FrameStartID);
|
||||
}
|
||||
|
||||
public bool TryGetNextFrame(out ReplayStep data, out int frameDiff, out bool inputDiff)
|
||||
public bool TryGetNextFrame(int targetFrame, bool indirectGet, out ReplayStep data, out int frameDiff, out bool inputDiff)
|
||||
{
|
||||
if (!bNetInit)
|
||||
{
|
||||
@ -74,37 +74,27 @@ namespace AxiReplay
|
||||
inputDiff = false;
|
||||
return false;
|
||||
}
|
||||
TakeFrame(1, out data, out frameDiff, out inputDiff);
|
||||
return frameDiff > 0;
|
||||
return TakeFrameToTargetFrame(targetFrame, indirectGet, out data, out frameDiff, out inputDiff);
|
||||
}
|
||||
|
||||
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);
|
||||
bool checkCanGetFrame(int targetFrame, bool indirectGet)
|
||||
{
|
||||
if (indirectGet)
|
||||
{
|
||||
return targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
return targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count >= frameProfiler.TempFrameCount(mRemoteForwardCount);
|
||||
}
|
||||
}
|
||||
|
||||
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 TakeFrameToTargetFrame(int targetFrame, bool indirectGet, out ReplayStep data, out int bFrameDiff, out bool inputDiff)
|
||||
{
|
||||
bool result;
|
||||
inputDiff = false;
|
||||
|
||||
|
||||
//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 >= frameProfiler.TempFrameCount(mRemoteForwardCount))
|
||||
if (checkCanGetFrame(targetFrame, indirectGet))
|
||||
{
|
||||
//当前帧追加
|
||||
mCurrClientFrameIdx = targetFrame;
|
||||
|
@ -1,19 +1,14 @@
|
||||
#pragma warning disable CS0618 // 类型或成员已过时
|
||||
|
||||
using AxibugEmuOnline.Client.ClientCore;
|
||||
using AxibugEmuOnline.Client.ClientCore;
|
||||
using AxibugProtobuf;
|
||||
using AxiReplay;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SocialPlatforms.Impl;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace AxibugEmuOnline.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// use <see cref="EmuCore{INPUTDATA}"/> instead
|
||||
/// </summary>
|
||||
[Obsolete("不可直接继承,需要继承EmuCore类型")]
|
||||
public abstract class IEmuCore : MonoBehaviour
|
||||
{
|
||||
public abstract class EmuCore : MonoBehaviour
|
||||
{
|
||||
/// <summary> 获得模拟器核心中的状态快照对象 </summary>
|
||||
public abstract object GetState();
|
||||
@ -43,62 +38,101 @@ namespace AxibugEmuOnline.Client
|
||||
/// <summary> 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0 </summary>
|
||||
public abstract uint Frame { get; }
|
||||
|
||||
public abstract bool PushEmulatorFrame();
|
||||
public abstract void PushEmulatorFrame();
|
||||
/// <summary> 模拟器核心推帧结束 </summary>
|
||||
public abstract void AfterPushFrame();
|
||||
protected abstract void AfterPushFrame();
|
||||
public abstract void GetAudioParams(out int frequency, out int channels);
|
||||
public abstract Texture OutputPixel { get; }
|
||||
public abstract RawImage DrawCanvas { get; }
|
||||
public abstract RawImage DrawCanvas { get; }
|
||||
|
||||
|
||||
/// <summary> 指示该游戏实例是否处于联机模式 </summary>
|
||||
public bool IsNetPlay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!App.user.IsLoggedIn) return false;
|
||||
if (App.roomMgr.mineRoomMiniInfo == null) return false;
|
||||
if (App.roomMgr.RoomState <= RoomGameState.OnlyHost) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class EmuCore<INPUTDATA> : IEmuCore
|
||||
/// <typeparam name="INPUTDATA">输入数据类型</typeparam>
|
||||
public abstract class EmuCore<INPUTDATA> : EmuCore
|
||||
{
|
||||
public sealed override bool PushEmulatorFrame()
|
||||
protected virtual bool EnableRollbackNetCode => false;
|
||||
|
||||
public sealed override void PushEmulatorFrame()
|
||||
{
|
||||
if (!TryPushEmulatorFrame()) return;
|
||||
|
||||
if (IsNetPlay) //skip frame handle
|
||||
{
|
||||
var skipFrameCount = App.roomMgr.netReplay.GetSkipFrameCount();
|
||||
if (skipFrameCount > 0) App.log.Debug($"SKIP FRAME : {skipFrameCount} ,CF:{App.roomMgr.netReplay.mCurrClientFrameIdx},RFIdx:{App.roomMgr.netReplay.mRemoteFrameIdx},RForward:{App.roomMgr.netReplay.mRemoteForwardCount} ,queue:{App.roomMgr.netReplay.mNetReplayQueue.Count}");
|
||||
for (var i = 0; i < skipFrameCount; i++)
|
||||
{
|
||||
if (!TryPushEmulatorFrame()) break;
|
||||
}
|
||||
}
|
||||
|
||||
AfterPushFrame();
|
||||
}
|
||||
|
||||
bool TryPushEmulatorFrame()
|
||||
{
|
||||
if (SampleInputData(out var inputData))
|
||||
{
|
||||
if (IsNetPlay) SendLocalInput();
|
||||
|
||||
return OnPushEmulatorFrame(inputData);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SendLocalInput()
|
||||
{
|
||||
var localState = GetLocalInput();
|
||||
var rawData = InputDataToNet(localState);
|
||||
App.roomMgr.SendRoomSingelPlayerInput(Frame, rawData);
|
||||
|
||||
if (m_lastTestInput != rawData)
|
||||
{
|
||||
m_lastTestInput = rawData;
|
||||
App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} Input F:{App.roomMgr.netReplay.mCurrClientFrameIdx} | I:{rawData}");
|
||||
}
|
||||
}
|
||||
|
||||
ulong m_lastTestInput;
|
||||
ReplayStep m_replayData;
|
||||
int m_frameDiff;
|
||||
bool m_inputDiff;
|
||||
protected bool SampleInputData(out INPUTDATA inputData)
|
||||
{
|
||||
bool result = false;
|
||||
inputData = default(INPUTDATA);
|
||||
|
||||
if (InGameUI.Instance.IsNetPlay)
|
||||
if (IsNetPlay)
|
||||
{
|
||||
ReplayStep replayData;
|
||||
int frameDiff;
|
||||
bool inputDiff;
|
||||
|
||||
if (App.roomMgr.netReplay.TryGetNextFrame((int)Frame, out replayData, out frameDiff, out inputDiff))
|
||||
{
|
||||
if (inputDiff)
|
||||
{
|
||||
App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} TryGetNextFrame remoteFrame->{App.roomMgr.netReplay.mRemoteFrameIdx} diff->{frameDiff} " +
|
||||
$"frame=>{replayData.FrameStartID} InPut=>{replayData.InPut}");
|
||||
if (App.roomMgr.netReplay.TryGetNextFrame((int)Frame, EnableRollbackNetCode ? true : false, out m_replayData, out m_frameDiff, out m_inputDiff))
|
||||
{
|
||||
if (m_inputDiff)
|
||||
{
|
||||
App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} TryGetNextFrame remoteFrame->{App.roomMgr.netReplay.mRemoteFrameIdx} diff->{m_frameDiff} " +
|
||||
$"frame=>{m_replayData.FrameStartID} InPut=>{m_replayData.InPut}");
|
||||
}
|
||||
|
||||
inputData = ConvertInputDataFromNet(replayData);
|
||||
inputData = ConvertInputDataFromNet(m_replayData);
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
var localState = GetLocalInput();
|
||||
var rawData = InputDataToNet(localState);
|
||||
if (m_lastTestInput != rawData)
|
||||
{
|
||||
m_lastTestInput = rawData;
|
||||
App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} Input F:{App.roomMgr.netReplay.mCurrClientFrameIdx} | I:{rawData}");
|
||||
}
|
||||
App.roomMgr.SendRoomSingelPlayerInput(Frame, rawData);
|
||||
}
|
||||
else//单机模式
|
||||
{
|
||||
@ -116,4 +150,3 @@ namespace AxibugEmuOnline.Client
|
||||
protected abstract bool OnPushEmulatorFrame(INPUTDATA InputData);
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618 // 类型或成员已过时
|
@ -167,7 +167,7 @@ public class UEssgee : EmuCore<ulong>
|
||||
return mUniKeyboard.DoLocalPressedKeys();
|
||||
}
|
||||
|
||||
public override void AfterPushFrame()
|
||||
protected override void AfterPushFrame()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ public class UMAME : EmuCore<ulong>
|
||||
return mUniKeyboard.DoLocalPressedKeys();
|
||||
}
|
||||
|
||||
public override void AfterPushFrame()
|
||||
protected override void AfterPushFrame()
|
||||
{
|
||||
mFPS.text = ($"fpsv {mUniVideoPlayer.videoFPS.ToString("F2")} fpsa {mUniSoundPlayer.audioFPS.ToString("F2")} ,Idx:{App.roomMgr.netReplay?.mCurrClientFrameIdx},RIdx:{App.roomMgr.netReplay?.mRemoteFrameIdx},RForward:{App.roomMgr.netReplay?.mRemoteForwardCount} ,RD:{App.roomMgr.netReplay?.mRemoteForwardCount} ,D:{App.roomMgr.netReplay?.mDiffFrameCount} ,Q:{App.roomMgr.netReplay?.mNetReplayQueue.Count}");
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public class UniKeyboard : MonoBehaviour, IKeyboard
|
||||
|
||||
public ulong GetPressedKeys()
|
||||
{
|
||||
if (InGameUI.Instance.IsNetPlay)
|
||||
if (InGameUI.Instance.Core.IsNetPlay)
|
||||
return CurrRemoteInpuAllData;
|
||||
else
|
||||
return CurrLocalInpuAllData;
|
||||
|
@ -149,7 +149,7 @@ namespace AxibugEmuOnline.Client
|
||||
}
|
||||
|
||||
|
||||
public override unsafe void AfterPushFrame()
|
||||
protected override unsafe void AfterPushFrame()
|
||||
{
|
||||
var screenBuffer = NesCore.ppu.GetScreenPtr();
|
||||
VideoProvider.SetDrawData(screenBuffer);
|
||||
|
@ -145,7 +145,7 @@ public class UStoicGoose : EmuCore<ulong>
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void AfterPushFrame()
|
||||
protected override void AfterPushFrame()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ namespace AxibugEmuOnline.Client.Manager
|
||||
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
|
||||
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
|
||||
/// </summary>
|
||||
private IEmuCore m_emuCore;
|
||||
private EmuCore m_emuCore;
|
||||
|
||||
private IControllerSetuper m_controllerSetuper;
|
||||
|
||||
@ -19,7 +19,7 @@ namespace AxibugEmuOnline.Client.Manager
|
||||
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
|
||||
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
|
||||
/// </summary>
|
||||
public IEmuCore Core => m_emuCore;
|
||||
public EmuCore Core => m_emuCore;
|
||||
|
||||
public AppEmu()
|
||||
{
|
||||
@ -53,14 +53,14 @@ namespace AxibugEmuOnline.Client.Manager
|
||||
switch (romFile.Platform)
|
||||
{
|
||||
case RomPlatformType.Nes:
|
||||
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("NES/NesEmulator")).GetComponent<IEmuCore>();
|
||||
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("NES/NesEmulator")).GetComponent<EmuCore>();
|
||||
break;
|
||||
case RomPlatformType.Cps1:
|
||||
case RomPlatformType.Cps2:
|
||||
case RomPlatformType.Igs:
|
||||
case RomPlatformType.Neogeo:
|
||||
case RomPlatformType.ArcadeOld:
|
||||
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("MAME/UMAME")).GetComponent<IEmuCore>();
|
||||
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("MAME/UMAME")).GetComponent<EmuCore>();
|
||||
break;
|
||||
case RomPlatformType.MasterSystem:
|
||||
case RomPlatformType.GameGear:
|
||||
@ -69,11 +69,11 @@ namespace AxibugEmuOnline.Client.Manager
|
||||
case RomPlatformType.ColecoVision:
|
||||
case RomPlatformType.Sc3000:
|
||||
case RomPlatformType.Sg1000:
|
||||
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("EssgeeUnity/EssgeeUnity")).GetComponent<IEmuCore>();
|
||||
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("EssgeeUnity/EssgeeUnity")).GetComponent<EmuCore>();
|
||||
break;
|
||||
case RomPlatformType.WonderSwan:
|
||||
case RomPlatformType.WonderSwanColor:
|
||||
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("StoicGooseUnity/StoicGooseUnity")).GetComponent<IEmuCore>();
|
||||
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("StoicGooseUnity/StoicGooseUnity")).GetComponent<EmuCore>();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -20,20 +20,7 @@ namespace AxibugEmuOnline.Client
|
||||
|
||||
public override bool Enable => gameObject.activeInHierarchy;
|
||||
|
||||
/// <summary> 指示该游戏实例是否处于联机模式 </summary>
|
||||
public bool IsNetPlay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!App.user.IsLoggedIn) return false;
|
||||
if (App.roomMgr.mineRoomMiniInfo == null) return false;
|
||||
if (App.roomMgr.RoomState <= RoomGameState.OnlyHost) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public IEmuCore Core { get; private set; }
|
||||
public EmuCore Core { get; private set; }
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
@ -69,18 +56,7 @@ namespace AxibugEmuOnline.Client
|
||||
//fluash netMsg
|
||||
NetMsg.Instance.DequeueNesMsg();
|
||||
|
||||
if (!Core.PushEmulatorFrame()) return;
|
||||
|
||||
if (IsNetPlay) //skip frame handle
|
||||
{
|
||||
var skipFrameCount = App.roomMgr.netReplay.GetSkipFrameCount();
|
||||
if (skipFrameCount > 0) App.log.Debug($"SKIP FRAME : {skipFrameCount} ,CF:{App.roomMgr.netReplay.mCurrClientFrameIdx},RFIdx:{App.roomMgr.netReplay.mRemoteFrameIdx},RForward:{App.roomMgr.netReplay.mRemoteForwardCount} ,queue:{App.roomMgr.netReplay.mNetReplayQueue.Count}");
|
||||
for (var i = 0; i < skipFrameCount; i++)
|
||||
if (!Core.PushEmulatorFrame())
|
||||
break;
|
||||
}
|
||||
|
||||
Core.AfterPushFrame();
|
||||
Core.PushEmulatorFrame();
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
@ -103,7 +79,7 @@ namespace AxibugEmuOnline.Client
|
||||
return m_state;
|
||||
}
|
||||
|
||||
public void Show(RomFile currentRom, IEmuCore core)
|
||||
public void Show(RomFile currentRom, EmuCore core)
|
||||
{
|
||||
m_delayCreateRoom = false;
|
||||
m_state = null; //清空游戏快照
|
||||
@ -186,14 +162,14 @@ namespace AxibugEmuOnline.Client
|
||||
{
|
||||
OverlayManager.PopSideBar(menus, 0, PopMenu_OnHide);
|
||||
|
||||
if (!IsNetPlay) //单人模式暂停模拟器
|
||||
if (!Core.IsNetPlay) //单人模式暂停模拟器
|
||||
Core.Pause();
|
||||
}
|
||||
|
||||
//菜单关闭时候
|
||||
private void PopMenu_OnHide()
|
||||
{
|
||||
if (!IsNetPlay) //单人模式恢复模拟器的暂停
|
||||
if (!Core.IsNetPlay) //单人模式恢复模拟器的暂停
|
||||
Core.Resume();
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
public class InGameUI_LoadStateQuick : ExecuteMenu
|
||||
{
|
||||
private InGameUI m_gameUI;
|
||||
public override bool Visible => !m_gameUI.IsNetPlay && m_gameUI.GetQuickState() != null;
|
||||
public override bool Visible => !m_gameUI.Core.IsNetPlay && m_gameUI.GetQuickState() != null;
|
||||
public override string Name => "快速读取";
|
||||
|
||||
public InGameUI_LoadStateQuick(InGameUI gameUI)
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
public override void OnExcute(OptionUI optionUI, ref bool cancelHide)
|
||||
{
|
||||
if (m_gameUI.IsNetPlay) return;
|
||||
if (m_gameUI.Core.IsNetPlay) return;
|
||||
|
||||
object state = m_gameUI.GetQuickState();
|
||||
if (state != null)
|
||||
|
@ -6,7 +6,7 @@ namespace AxibugEmuOnline.Client
|
||||
{
|
||||
private InGameUI m_gameUI;
|
||||
public override string Name => "复位";
|
||||
public override bool Visible => !m_gameUI.IsNetPlay || App.roomMgr.IsHost;
|
||||
public override bool Visible => !m_gameUI.Core.IsNetPlay || App.roomMgr.IsHost;
|
||||
|
||||
public InGameUI_Reset(InGameUI gameUI)
|
||||
{
|
||||
@ -15,7 +15,7 @@ namespace AxibugEmuOnline.Client
|
||||
|
||||
public override void OnExcute(OptionUI optionUI, ref bool cancelHide)
|
||||
{
|
||||
if (!m_gameUI.IsNetPlay)
|
||||
if (!m_gameUI.Core.IsNetPlay)
|
||||
{
|
||||
App.emu.ResetGame();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ namespace AxibugEmuOnline.Client
|
||||
{
|
||||
private InGameUI m_gameUI;
|
||||
|
||||
public override bool Visible => !m_gameUI.IsNetPlay;
|
||||
public override bool Visible => !m_gameUI.Core.IsNetPlay;
|
||||
public override string Name => "快速保存";
|
||||
|
||||
public InGameUI_SaveStateQuick(InGameUI gameUI)
|
||||
@ -17,7 +17,7 @@ namespace AxibugEmuOnline.Client
|
||||
|
||||
public override void OnExcute(OptionUI optionUI, ref bool cancelHide)
|
||||
{
|
||||
if (m_gameUI.IsNetPlay) return;
|
||||
if (m_gameUI.Core.IsNetPlay) return;
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
object state = m_gameUI.Core.GetState();
|
||||
|
Loading…
Reference in New Issue
Block a user