new_10009_YanCheng_Metrology/Assets/Template/Scripts/Project/Manager/ReconnectMgr.cs

341 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using LitJson;
using System;
using Unity.Burst.CompilerServices;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;
/// <summary>
/// 断线重连管理
/// </summary>
public class ReconnectMgr : SingletonMono<ReconnectMgr>
{
[HideInInspector]
public string localStatFileName = "realtimeStat.json";//保存文件的文件名
[HideInInspector]
public int countDown_AutoSave = 600;//自动保存的时间间隔
private TB_UserExamStat UserExamStat = new TB_UserExamStat();
private string localStatPath = "";
private Coroutine coroutine;//自动保存倒计时
//[HideInInspector]
//public List<string> experiencedScene = new List<string>();//用户经历过的场景
/// <summary>
/// 初始化函数,记录时间间隔
/// </summary>
public void Init()
{
localStatPath = Application.streamingAssetsPath + "/" + localStatFileName;
//UserExamStat.experiencedScene.Clear();//清空用户经历过的场景
//experiencedScene.Clear();
}
/// <summary>
/// 用户每经历一个场景就需要保存一个场景的数据
/// </summary>
//public bool IntoNewScene(string sceneName)
//{
// if (UserExamStat.experiencedScene.Contains(sceneName))
// return false;
// else
// {
// UserExamStat.experiencedScene.Add(sceneName);
// return true;
// }
//}
ReconnectMgr()//构造函数
{
Init();
}
/// <summary>
/// 记录用户状态
/// </summary>
public void RealtimeStatWriter()
{
//记录步骤相关各项信息
UserExamStat.schemeID = ProcessManager.Instance.schemeID;
//记录得分情况
ScoreBase scoreBase = FindFirstObjectByType<ScoreBase>();
UserExamStat.systemID = scoreBase.systemId;
UserExamStat.allSubScore.Clear();
if (scoreBase != null)
{
foreach (var item in scoreBase.GetStepScore())
{
ReconnectSubScoreInfo sub = new ReconnectSubScoreInfo();
sub.index = item.Key;
sub.subProcessId = item.Value.subProcessId;
sub.currentScore = item.Value.currentScore;
sub.isDone = item.Value.isDone;
UserExamStat.allSubScore.Add(sub);
};
//保存场景内独有信息
UserExamStat.currentSceneOtherInfo = scoreBase.SaveSceneBufferList();
}
//记录装备材料信息
UserExamStat.allToolAndMaterial.Clear();
UserExamStat.currentSceneTools.Clear();
Dictionary<string, List<ItemInfo>> toolAndMaterialDic = PacksackBagMgr.Instance.GetCurrentBagData();
foreach (var item in toolAndMaterialDic)
{
foreach (var itemInfo in item.Value)
{
UserExamStat.allToolAndMaterial.Add(((ItemInfo)itemInfo).toolName);
ReconnectItemInfo rec = new ReconnectItemInfo();//获取场景内(工具间)所有可以装备材料的物品
rec.toolId = itemInfo.toolId;
rec.toolName = itemInfo.toolName;
rec.triggerID = itemInfo.triggerID;
//rec.toolOrDeviceOrMaterial = item.itemInfo.toolOrDeviceOrMaterial;
rec.selfPosInToolRoom = itemInfo.selfPosInToolRoom;
UserExamStat.currentSceneTools.Add(rec);
}
}
//记录已穿戴设备
UserExamStat.allWear.Clear();
Dictionary<string, ItemInfo> wearDic = PacksackBagMgr.Instance.wearDic;
foreach (var item in wearDic)
{
UserExamStat.allWear.Add(((ItemInfo)item.Value).toolName);
}
//获取当前所加载场景的名字
UserExamStat.sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
//获取场景内(现场)所有可以出发的装置
UserExamStat.currentSceneTriggers.Clear();
PermanentTriggerBase[] allPermanentTriggers = FindObjectsOfType<PermanentTriggerBase>();
foreach (PermanentTriggerBase item in allPermanentTriggers)
{
ReconnectTriggerInfo ret = new ReconnectTriggerInfo();
ret.triggerName = item.triggerName;
ret.triggerID = item.triggerID;
ret.selfPosInScene = item.transform.localPosition;
ret.selfRotInScene = item.transform.localEulerAngles;
ret.triggerInfo = GetTriggerAttribute(item);//item.SaveCurrentTriggerStat();
UserExamStat.currentSceneTriggers.Add(ret);
}
//转换为JSON
var settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
settings.Formatting = Formatting.Indented;//避免循环引用(继承其他类)
string UserJson = JsonConvert.SerializeObject(UserExamStat, settings);
Debug.Log("自动保存成功");
File.WriteAllText(localStatPath, UserJson);
}
/// <summary>
/// 获取常驻交互的属性
/// </summary>
/// <param name="permanentTriggerBase"></param>
public string GetTriggerAttribute(PermanentTriggerBase permanentTriggerBase)
{
JsonData ptbData = new JsonData();
FieldInfo[] fieldInfo = permanentTriggerBase.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fieldInfo)
{
if (field.GetCustomAttribute<ReconnetAtrribute>() != null)
{
ReconnetAtrribute attribute = field.GetCustomAttribute<ReconnetAtrribute>();
object value = field.GetValue(permanentTriggerBase);
ptbData[field.Name] = value.ToString();
}
}
//return Regex.Unescape(ptbData.ToJson());
return ptbData.ToJson();
}
public void SetTriggerAttribute(string triggerJson, PermanentTriggerBase permanentTriggerBase)
{
JsonData ptbData = JsonMapper.ToObject<JsonData>(triggerJson);
FieldInfo[] fieldInfo = permanentTriggerBase.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fieldInfo)
{
if (field.GetCustomAttribute<ReconnetAtrribute>() != null)
{
try
{
ReconnetAtrribute attribute = field.GetCustomAttribute<ReconnetAtrribute>();
Type type = field.GetValue(permanentTriggerBase).GetType();
string tmp = ptbData[field.Name].ToString();
field.SetValue(permanentTriggerBase, Convert.ChangeType(tmp, type));
}catch (Exception ex) {
Debug.LogError("SetTriggerAttribute恢复错误" + ex.ToString());
}
}
}
}
/// <summary>
/// 读取用户状态(先使用同步,后用异步)
/// </summary>
public bool RealtimeStatReader()
{
if (File.Exists(localStatPath))
{
try
{
StreamReader sr = new StreamReader(localStatPath);
string user_last_stat = sr.ReadToEnd();
sr.Close();
UserExamStat = JsonMapper.ToObject<TB_UserExamStat>(user_last_stat);
return true;
}
catch (System.Exception e)
{
Debug.LogError(e.ToString());
return false;
}
}
else
{
return false;
}
}
/// <summary>
/// 恢复现场
/// </summary>
public void RecoverScene()
{
//先恢复场景
ScenesManager.Instance.LoadSceneAsyn(UserExamStat.sceneName, () =>
{
//右侧工具栏切换
if (!GameManager.UIMgr.GetPanel<UI_MenuBar>())//office场景下,右侧工具栏可能会隐藏
{
GameManager.UIMgr.ShowPanel<UI_MenuBar>(E_UI_Layer.Mid, (panel) =>
{
panel.Init();
GameManager.EventMgr.EventTrigger(Enum_EventType.SwitchScene, GameManager.RunModelMgr.SceneType);
});
}
else
GameManager.EventMgr.EventTrigger(Enum_EventType.SwitchScene, GameManager.RunModelMgr.SceneType);
//恢复背包中的装备
TooRoomMannger tooRoomMannger = FindAnyObjectByType<TooRoomMannger>();
List<ItemInfo> itemInPack = ToolAndmaterialMgr.Instance.CreateItemInfoByName(UserExamStat.allToolAndMaterial);
foreach (ItemInfo item in itemInPack)
{
for (int j = 0; j < UserExamStat.currentSceneTools.Count; j++)
{
if (item.toolName == UserExamStat.currentSceneTools[j].toolName)
{
item.selfPosInToolRoom = UserExamStat.currentSceneTools[j].selfPosInToolRoom;
UserExamStat.currentSceneTools.RemoveAt(j);
break;
}
}
PacksackBagMgr.Instance.AddOneToolOrMater(item);
}
if (tooRoomMannger != null) tooRoomMannger.RemoveRepeat();
//恢复已穿戴的装备
List<ItemInfo> itemWear = ToolAndmaterialMgr.Instance.CreateItemInfoByName(UserExamStat.allWear);
foreach (ItemInfo item in itemWear)
{
PacksackBagMgr.Instance.WearItemState(item, true);
if (tooRoomMannger != null)//如果在工具间,则修改穿着
{
tooRoomMannger.Wear(item.toolName, true);
}
}
//恢复场景内各个触发器状态
PermanentTriggerBase[] allPermanentTriggers = FindObjectsOfType<PermanentTriggerBase>();
List<ReconnectTriggerInfo> allReconTrigs = UserExamStat.currentSceneTriggers;
foreach (PermanentTriggerBase item in allPermanentTriggers)
{
item.gameObject.SetActive(false);
foreach (ReconnectTriggerInfo ret in allReconTrigs)
{
if (item.triggerName == ret.triggerName)
{
item.gameObject.SetActive(true);
if (item.gameObject.GetComponent<Tool_SelectComponent>() == null)//工具材料已经恢复过了
{
item.transform.localPosition = ret.selfPosInScene;
item.transform.localEulerAngles = ret.selfRotInScene;
SetTriggerAttribute(ret.triggerInfo, item);
//item.LoadCurrentTriggerStat(ret.triggerInfo);
}
break;
}
}
}
//恢复记录的分数
ScoreBase scoreBase = FindFirstObjectByType<ScoreBase>();
if (scoreBase != null)
{
Dictionary<int, ScoreSubjectStep> reconnectScore = scoreBase.GetStepScore();
foreach (var item in UserExamStat.allSubScore)
{
if (reconnectScore.ContainsKey(item.index))
{
reconnectScore[item.index].currentScore = item.currentScore;
reconnectScore[item.index].isDone = item.isDone;
}
}
scoreBase.setCurrentScore(UserExamStat.currentScore);
scoreBase.LoadSceneBufferList(UserExamStat.currentSceneOtherInfo);
}
});
}
/// <summary>
/// 自动保存用户状态,
/// </summary>
/// <returns></returns>
private IEnumerator AutoSaveStat()
{
int countDown = countDown_AutoSave;
WaitForSeconds waitForSeconds = new WaitForSeconds(1);
while (countDown > 0)
{
yield return waitForSeconds;
//Exam为考试模式,Practice为练习模式,考试模式加入后,进入要重置时间,重新启动
if (ProcessManager.Instance.mode == E_ModeType.Practice)
{
countDown--;
//Debug.Log("自动保存倒计时:" + countDown);
if (countDown <= 0)
{
ReconnectMgr.Instance.RealtimeStatWriter();//需要在GameManager里面初始化
Debug.Log("完成状态自动保存");
countDown = countDown_AutoSave;
}
}
}
}
private void Start()
{
coroutine = StartCoroutine(AutoSaveStat());
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.T))//测试用,按T读取状态保存
{
RealtimeStatWriter();
Debug.Log("当前场景:" + UserExamStat.sceneName);
}
else if (Input.GetKeyDown(KeyCode.Y))
{
RealtimeStatReader();
RecoverScene();
}
}
}