using AxibugEmuOnline.Client.ClientCore;
using AxibugProtobuf;
using AxiReplay;
using System;
using UnityEngine;
using UnityEngine.UI;
namespace AxibugEmuOnline.Client
{
public abstract class EmuCore : 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 void PushEmulatorFrame();
/// 模拟器核心推帧结束
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 Vector3 DrawLocalScale { get; }
/// 指示该游戏实例是否处于联机模式
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 : EmuCore
{
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()
{
INPUTDATA inputData;
if (SampleInputData(out 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 (IsNetPlay)
{
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(m_replayData);
result = true;
}
else
{
result = false;
}
}
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);
}
}