#pragma warning disable CS0618 // 类型或成员已过时 using AxibugEmuOnline.Client.ClientCore; using AxibugProtobuf; using AxiReplay; using System; using UnityEngine; using UnityEngine.UI; namespace AxibugEmuOnline.Client { /// /// use instead /// [Obsolete("不可直接继承,需要继承EmuCore类型")] public abstract class IEmuCore : MonoBehaviour { /// 获得模拟器核心中的状态快照对象 public abstract object GetState(); /// 获得模拟器核心中的状态快照字节数据 public abstract byte[] GetStateBytes(); /// 加载状态快照 /// 该对象应该来自核心的方法的返回值,或是从返回的byte数组构建 public abstract void LoadState(object state); /// 加载状态快照 /// 该对象应该来自核心的返回的byte数组 public abstract void LoadStateFromBytes(byte[] data); /// 暂停核心推帧 public abstract void Pause(); /// 恢复核心推帧(从Pause状态恢复) public abstract void Resume(); /// 启动模拟器逻辑 public abstract MsgBool StartGame(RomFile romFile); /// 释放模拟器核心 public abstract void Dispose(); /// 重置核心,通常由模拟器核心提供的功能 public abstract void DoReset(); /// 获得模拟器核心的控制器设置器 /// public abstract IControllerSetuper GetControllerSetuper(); /// 核心所属平台 public abstract RomPlatformType Platform { get; } /// 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0 public abstract uint Frame { get; } public abstract bool PushEmulatorFrame(); /// 模拟器核心推帧结束 public 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 class EmuCore : IEmuCore { public sealed override bool PushEmulatorFrame() { if (SampleInputData(out var inputData)) { return OnPushEmulatorFrame(inputData); } return false; } ulong m_lastTestInput; protected bool SampleInputData(out INPUTDATA inputData) { bool result = false; inputData = default(INPUTDATA); if (InGameUI.Instance.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}"); } inputData = ConvertInputDataFromNet(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//单机模式 { inputData = GetLocalInput(); result = true; } return result; } protected abstract INPUTDATA GetLocalInput(); protected abstract INPUTDATA ConvertInputDataFromNet(ReplayStep step); protected abstract ulong InputDataToNet(INPUTDATA inputData); /// 模拟器核心推帧 protected abstract bool OnPushEmulatorFrame(INPUTDATA InputData); } } #pragma warning restore CS0618 // 类型或成员已过时