Forest_Client/Forest/Assets/Scripts/Gameplay2/BuildManager.cs

571 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using PhxhSDK;
using UnityEngine;
using System.Linq;
using LC.Newtonsoft.Json;
using Framework.Constants;
using Sirenix.OdinInspector;
using Cysharp.Threading.Tasks;
using System.Collections.Generic;
using UnityEngine.AddressableAssets;
namespace Framework.Manager
{
/// <summary>
/// 解锁类型
/// </summary>
public enum UnlockType
{
[LabelText("按挂点解锁")] ForGroup,
[LabelText("按主题解锁")] ForThematic,
}
/// <summary>
/// 解锁条件类型
/// </summary>
public enum UnlockConditionType
{
[LabelText("关卡解锁")] Level,
[LabelText("金币解锁")] Coin,
}
[Serializable]
public class BuildData
{
[ReadOnly] public string buildID;
[LabelText("挂点数量")] public int nodeCount;
[LabelText("主题数量")] public int thematicCount;
[LabelText("解锁类型")] [SerializeField] public UnlockType unlockType;
[LabelText("解锁条件类型")] [SerializeField] public UnlockConditionType unlockConditionType;
[LabelText("解锁条件")] public List<UnlockInfo> unlockInfos;
[LabelText("挂点数据")] public List<BuildNode> NodeInfos;
[Serializable]
public class UnlockInfo
{
[LabelText("条件")] public int condition;
//主题 or 挂点
[LabelText("对应组")] public int conditionGroup;
[LabelText("前置组")] public int preGroup;
}
[Serializable]
public class BuildNode
{
[LabelText("挂点名称")] [ReadOnly] public string Name;
[HideInInspector] public List<string> Options;
[HideInInspector] public string IconPath;
[JsonConstructor]
public BuildNode(string name)
{
this.Name = name;
this.Options = new List<string>();
this.IconPath = string.Empty;
}
public BuildNode()
{
}
}
}
/// <summary>
/// 节点信息类
/// </summary>
public class NodeInfo
{
public string Name;
public Dictionary<string, OptionInfo> Options;
//按挂点解锁条件
public int Condition;
//前置解锁组
public string PreGroup;
public string IconPath;
public OptionInfo GetOptionInfo(string optionID = null)
{
if (optionID == null) optionID = "Option1";
return Options.GetValueOrDefault(optionID);
}
}
/// <summary>
/// 节点选项类
/// </summary>
public class OptionInfo
{
public string Name;
public string IconPath;
//按主题解锁条件
public int Condition;
//前置主题
public string PreThematic;
}
/// <summary>
/// 玩家养成建造存盘数据
/// </summary>
public class UserBuildInfo
{
public int GuideGroup;
public string BuildData = NormalConstants.DefaultBuildID;
public Dictionary<string, string> ChooseNodeInfo;
public UserBuildInfo()
{
ChooseNodeInfo = new Dictionary<string, string>();
}
public UserBuildInfo(string buildData)
{
DebugUtil.LogError("建造新的buildDAta {0}", buildData);
BuildData = buildData;
ChooseNodeInfo = new Dictionary<string, string>();
}
}
public class BuildManager
{
public const string UserBuildSaveKey = "UserBuildInfo";
public const string DefaultBuildID = "Build_1";
private const string NodeName = "Node{0}";
private const string OptionName = "Option{0}";
private static BuildManager _instance;
public static BuildManager Instance
{
get
{
if (_instance == null)
{
_instance = new BuildManager();
}
return _instance;
}
}
public Dictionary<string, NodeInfo> NodeInfos;
public NodeInfo CurIUnlockNodeInfo;
public bool IsChanging = false;
/// <summary>
/// 更换场景
/// </summary>
public bool ChangeBuildSceneID;
//玩家存盘选择信息
private UserBuildInfo _userBuildInfo;
public UserBuildInfo UserBuildInfo
{
get => _userBuildInfo;
private set => _userBuildInfo = value;
}
//已达到的条件
public int ReachCondition
{
get => _reachCondition;
private set => _reachCondition = value;
}
private int _reachCondition = -1;
//动态加载的图标
private Dictionary<string, Sprite> _iconSprites;
//当前场景蓝图
public Sprite CurBlueprint;
//Build场景相机
public Camera CurBuildCamera;
private BuildData _curBuildData;
private bool _isInit;
private bool _isInGame;
public async UniTask Init(BuildData buildData, bool inGame = false, UserBuildInfo userBuildInfo = null)
{
if (_isInit && !ChangeBuildSceneID) return;
_curBuildData = buildData;
NodeInfos = new Dictionary<string, NodeInfo>();
_iconSprites = new Dictionary<string, Sprite>();
InitNodesInfo();
InitUserBuildInfo(userBuildInfo);
InitCondition();
await InitIcon();
InitBlueprint();
_isInGame = inGame;
if (inGame)
CurBuildCamera = CameraManager.Instance.UICamera;
_isInit = true;
}
/// <summary>
/// 初始化该Build场景的节点信息
/// </summary>
private void InitNodesInfo()
{
try
{
foreach (var node in _curBuildData.NodeInfos)
{
var nodeInfo = new NodeInfo
{
Name = node.Name,
Options = new Dictionary<string, OptionInfo>(),
IconPath = node.IconPath
};
foreach (var option in node.Options)
{
var optionInfo = new OptionInfo()
{
Name = option
};
nodeInfo.Options.Add(option, optionInfo);
}
NodeInfos.Add(nodeInfo.Name, nodeInfo);
}
}
catch (Exception e)
{
DebugUtil.LogError("BuildManager.InitNodesInfo 初始化节点错误 :{0}", e);
}
}
/// <summary>
/// 初始化存盘信息
/// </summary>
private void InitUserBuildInfo(UserBuildInfo userBuildInfo)
{
try
{
if(_isInit)return;
//游戏中传入数据
if (userBuildInfo != null)
{
_userBuildInfo = userBuildInfo;
}
else
{
StorageManager.Instance.Init();
_userBuildInfo =
StorageManager.Instance.GetStorage<UserBuildInfo>(UserBuildSaveKey);
if (_userBuildInfo == null)
{
var buildId = _curBuildData.buildID;
_userBuildInfo = new UserBuildInfo(buildId);
}
}
foreach (var nodeInfo in NodeInfos)
{
if (_userBuildInfo.ChooseNodeInfo.TryGetValue(nodeInfo.Key, out var option))
{
continue;
}
/*var optionInfo = nodeInfo.Value.GetOptionInfo();
if (optionInfo == null) return;
_userBuildInfo.ChooseNodeInfo.TryAdd(nodeInfo.Key, optionInfo.Name);*/
_userBuildInfo.ChooseNodeInfo.TryAdd(nodeInfo.Key, "");
}
//DebugUserChooseNode();
}
catch (Exception e)
{
DebugUtil.LogError("BuildManager.InitUserBuildInfo 初始玩家信息错误 :{0}", e);
}
}
/// <summary>
/// 初始化条件
/// </summary>
private void InitCondition()
{
try
{
switch (_curBuildData.unlockType)
{
case UnlockType.ForGroup:
{
foreach (var unlockInfo in _curBuildData.unlockInfos)
{
var nodeName = string.Format(NodeName, unlockInfo.conditionGroup);
if (NodeInfos.TryGetValue(nodeName, out var nodeInfo))
{
nodeInfo.Condition = unlockInfo.condition;
var nextNode = string.Format(NodeName, unlockInfo.preGroup);
nodeInfo.PreGroup = nextNode;
//DebugUtil.LogError("挂点解锁:节点{0}的解锁条件是: {1}, 前置解锁组是: {2}", nodeInfo.Name, unlockInfo.condition, nextNode);
}
}
break;
}
case UnlockType.ForThematic:
{
foreach (var unlockInfo in _curBuildData.unlockInfos)
{
var optionName = string.Format(OptionName, unlockInfo.conditionGroup);
foreach (var nodeInfo in NodeInfos.Values)
{
if (nodeInfo.Options.TryGetValue(optionName, out var optionInfo))
{
optionInfo.Condition = unlockInfo.condition;
var nextOption = string.Format(OptionName, unlockInfo.preGroup);
optionInfo.PreThematic = nextOption;
DebugUtil.LogError("主题解锁:节点{0}的选项{1}的解锁条件是:{2}, 前置解锁主题是: {3}", nodeInfo.Name,
optionInfo.Name,
unlockInfo.condition, nextOption);
}
}
}
break;
}
}
}
catch (Exception e)
{
DebugUtil.LogError("BuildManager.InitCondition 初始化条件错误 :{0}", e);
}
}
/// <summary>
/// 异步加载该建造物品图标
/// </summary>
private async UniTask InitIcon()
{
try
{
foreach (var nodeInfo in NodeInfos.Values)
{
foreach (var optionInfo in nodeInfo.Options.Values)
{
optionInfo.IconPath = await InitOptionIcon(nodeInfo.IconPath, optionInfo.Name);
}
}
}
catch (Exception e)
{
DebugUtil.LogError("BuildManager.InitIcon 初始化图标数据错误 :{0}", e);
}
}
/// <summary>
/// 初始化加载选项图标
/// </summary>
private async UniTask<string> InitOptionIcon(string iconsPath, string optionName)
{
try
{
var path = string.Format(iconsPath, optionName);
var assetPath = path.Replace(Application.dataPath, "").Replace('\\', '/');
var sprite = await AssetManager.Instance.LoadAssetAsync<Sprite>(assetPath);
if (_iconSprites.TryAdd(path, sprite))
return path;
return null;
}
catch (Exception e)
{
DebugUtil.LogError("BuildManager.InitOptionIcon 加载选项图标错误, 路径: {0}, Error: {1}", iconsPath, e);
return null;
}
}
/// <summary>
/// 加载当前场景蓝图
/// </summary>
private async void InitBlueprint()
{
try
{
var path = string.Format(Constants.PathConstants.BuildBlueprint, _curBuildData.buildID);
CurBlueprint = await AssetManager.Instance.LoadAssetAsync<Sprite>(path);
}
catch (Exception e)
{
DebugUtil.LogError("BuildManager.InitBlueprint 加载蓝图错误 :{0}", e);
}
}
/// <summary>
/// 更换建造场景
/// </summary>
public async void ChangeBuildScene()
{
var buildId = _curBuildData.buildID.Equals(NormalConstants.DefaultBuildID) ? "Build_2" : "Build_1";
var buildPath = string.Format(Framework.Constants.PathConstants.SceneBuildPath, buildId);
await Addressables.LoadSceneAsync(buildPath).ToUniTask();
}
/// <summary>
/// 获得选项Icon图标
/// </summary>
public Sprite GetOptionIcon(string nodeName, string optionName)
{
if (NodeInfos.TryGetValue(nodeName, out var nodeInfo))
{
if (nodeInfo.Options.TryGetValue(optionName, out var optionInfo))
{
if (_iconSprites.TryGetValue(optionInfo.IconPath, out var sprite))
return sprite;
}
}
return null;
}
/// <summary>
/// 根据节点获得解锁条件
/// </summary>
public int GetCondition(string nodeName)
{
var condition = 0;
if (NodeInfos.TryGetValue(nodeName, out var nodeInfo))
{
condition = nodeInfo.Condition;
}
return condition;
}
public void SaveNodeInfo(string node, string option)
{
if (_userBuildInfo.ChooseNodeInfo.TryGetValue(node, out var oldOption))
{
_userBuildInfo.ChooseNodeInfo[node] = option;
DebugUtil.LogY($"节点{node}保存了{option}选择");
}
else
{
DebugUtil.LogWarning("玩家Build存档信息没有 {0} 节点信息,请检查初始化", node);
_userBuildInfo.ChooseNodeInfo.Add(node, option);
}
StorageManager.Instance.SaveWithoutUpdate();
}
/// <summary>
/// 获取下一个解锁节点
/// </summary>
public string GetNextLockNode()
{
string nodeName = null;
switch (_curBuildData.unlockType)
{
case UnlockType.ForGroup:
{
foreach (var node in NodeInfos)
{
if (_userBuildInfo.ChooseNodeInfo.TryGetValue(node.Key, out var curNode) &&
_userBuildInfo.ChooseNodeInfo.TryGetValue(node.Value.PreGroup, out var preNode))
{
//当前节点位选择且前置节点已选择
if (string.IsNullOrEmpty(curNode) && !string.IsNullOrEmpty(preNode))
{
//DebugUtil.LogError("下一个节点是{0}", node.Key);
return node.Key;
}
}
}
var firstNode = NodeInfos
.OrderBy(kv => kv.Value.Condition)
.FirstOrDefault();
return firstNode.Key;
}
//TODO 按主题解锁
default:
break;
}
//DebugUtil.LogError("得到最小的节点是{0}", nodeName);
return nodeName;
}
/// <summary>
/// 更新已经达到的条件
/// </summary>
public void UpdateReachCondition(int condition)
{
//TODO 分场景 、解锁类型、解锁条件
_reachCondition = condition;
}
/// <summary>
/// 更新本地节点选择
/// </summary>
public void SetBuildUserInfo(int guideGroupID)
{
_userBuildInfo.GuideGroup = guideGroupID;
StorageManager.Instance.SyncForce = true;
}
/// <summary>
/// 播放音效
/// </summary>
public void PlaySound()
{
if (_isInGame)
AudioManager.Instance.PlaySound(AudioType.SOUND, "S_Btn",
new UnityAudio(false));
}
/// <summary>
/// Debug 清楚玩家所有选择
/// </summary>
public void ClearOption()
{
foreach (var node in NodeInfos)
{
if (_userBuildInfo.ChooseNodeInfo.TryGetValue(node.Key, out var option))
_userBuildInfo.ChooseNodeInfo[node.Key] = "";
}
DebugUserChooseNode();
StorageManager.Instance.SyncForce = true;
}
private void DebugUserChooseNode()
{
foreach (var infos in _userBuildInfo.ChooseNodeInfo)
{
DebugUtil.LogError("节点 {0} 选择的的是 {1}", infos.Key, infos.Value);
}
}
public void Release()
{
}
}
}