zxl
/
CTT
forked from Cal/CTT
1
0
Fork 0
CTT/Unity/Assets/XNodeDemo/NewSkill/Node/RootNode.cs

495 lines
19 KiB
C#

using Cal;
using ET;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
using XNode;
public static class NodeDataUtil
{
public static Dictionary<int, SkillNodeGraph> dic;
}
public class RootNode : SkillNode
{
// Use this for initialization
protected override void Init()
{
base.Init();
skillGraph = base.graph as SkillNodeGraph;
}
[LabelText("修改技能Id")]
[LabelWidth(80)]
[InlineButton("ChangeSkillId", "确定")]
public int skillId;
void ChangeSkillId()
{
skillLogic.skillId = skillId;
}
[SerializeField]
public Cal.SkillLogicConfig skillLogic;
[PropertySpace(15, 12)]
[LabelText("技能事件条件")]
[BsonIgnore]
[Output] public float result;
// GetValue should be overridden to return a value for any specified output port
public override object GetValue(NodePort port)
{
return null;
}
public override void OnCreateConnection(NodePort from, NodePort to)
{
if (to.node == this)
{
}
else
if (!(to.node is SkillEventConditionNode))
{
from.Disconnect(to);
}
}
static string saveSODataDir = "Assets/XNodeDemo/Assets/SOData/";
static string soDir = "Assets/XNodeDemo/Assets/Skill/";
[LabelText("存档保存路径"), PropertyOrder(120)]
static string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "/CTT/Skill/Skill";
[FolderPath(AbsolutePath = true)]
[LabelText("日志保存路径"), PropertyOrder(120)]
static string logPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "/CTT/Skill/Logs";
[LabelText("文件名"), PropertyOrder(120)]
static string fileName = "SkillLogicConfig.json";
[LabelText("二进制文件名"), PropertyOrder(120)]
static string fileBytesName = "SkillLogicConfig.bytes";
static string logDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "/CTT/Nodes/Logs";
static string configDir = "Assets/Download/Config/";
private List<SkillNodeGraph> GetSkills()
{
var arr = Utility.FileOpation.GetFiles(soDir, "*.asset", SearchOption.AllDirectories);
List<SkillNodeGraph> list = new List<SkillNodeGraph>();
foreach (var item in arr)
{
var asset = AssetDatabase.LoadAssetAtPath<SkillNodeGraph>(Utility.Path.DataPathToAssetPath(item.FullName));
list.Add(asset);
}
return list;
}
//[Button("Test")]
//[ButtonGroup]
void TestModify()
{
var arr = GetSkills();
foreach (var asset in arr)
{
var rootNode = asset.nodes.Find(t => t is RootNode)as RootNode;
if (rootNode != null)
{
var param = rootNode.skillLogic.cast;
if(param.skillCastType == SkillCastType.)
{
param.skillCast /= 10f;
rootNode.skillLogic.cast = param;
EditorUtility.SetDirty(asset);
}
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Log.Info($"修改{DateTime.Now:MM_dd+HH_mm_ss}");
}
#region Serialize
[Button("序列化")]
[ButtonGroup]
void Serilize()
{
RegisterMongo();
var arr = GetSkills();
StringBuilder sb = new StringBuilder();
sb.AppendLine("[");
foreach (var asset in arr)
{
asset.nodes.ForEach(t =>
{
int id = t.As<SkillNode>().uniqeId;
if (id >= asset.maxUniqeId)
asset.maxUniqeId = ++id;
if(t is ModifierNode modifierNode)
{
int modifierId = modifierNode.modifier.Id.Value % 100;
if (modifierId >= asset.maxModifierId)
asset.maxModifierId = ++modifierId;
}
});
foreach (SkillNode node in asset.nodes)
{
GenerateNestIds(node);
}
EditorUtility.SetDirty(asset);
sb.Append($"[{asset.Id},{ MongoHelper.ToJson(asset)}],\n");
}
sb.AppendLine("]");
string path = Path.Combine(saveSODataDir, $"nodes.json");
string logPath = Path.Combine(logDir, $"nodes_{DateTime.Now:MM_dd+HH_mm_ss}.json");
string str = sb.ToString();
Utility.FileOpation.Delete(path);
Utility.FileOpation.CreateDirectory(logDir);
File.WriteAllText(path, str);
File.WriteAllText(logPath, str);
SerilizeToConfig(arr);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Log.Info($"保存成功{DateTime.Now:MM_dd+HH_mm_ss} {str.Length / 1024f:f1}K");
}
private void SerilizeToConfig(List<SkillNodeGraph> arr)
{
string configPath = Path.Combine(configDir, "SkillLogicConfig.json");
Utility.FileOpation.CreateDirectory(path);
string newpath = Path.GetFullPath(Path.Combine(path, fileName));
Utility.FileOpation.Delete(newpath);
string saveath = logPath;
Utility.FileOpation.CreateDirectory(saveath);
saveath += $"/SkillLogicConfig+{DateTime.Now:MM-dd + HH-mm-ss}.json";
SkillLogicConfigCollection data = new SkillLogicConfigCollection();
foreach (var skillNodeGraph in arr)
{
int id = skillNodeGraph.Id;
SkillLogicConfig skillLogicConfig = new SkillLogicConfig();
RootNode rootNode = skillNodeGraph.Root;
rootNode.skillLogic.Clone(skillLogicConfig);
data.skillDic.Add(id, skillLogicConfig);
SerilizeSkillEvent(rootNode, skillLogicConfig);
SerilizeModifier(skillNodeGraph, skillLogicConfig);
}
string str = MongoHelper.ToJson(data);
Utility.FileOpation.Delete(configPath);
File.WriteAllText(configPath, str);
File.WriteAllText(newpath, str);
File.WriteAllText(saveath, str);
Log.Info($"保存Config成功{DateTime.Now:MM_dd+HH_mm_ss} {str.Length / 1024f:f1}K");
SerilizeBson(data);
}
private void SerilizeBson(SkillLogicConfigCollection data)
{
string newpath = Path.GetFullPath(Path.Combine(path, fileBytesName));
string serPath = Path.GetFullPath(Path.Combine("../Config/Skill", fileBytesName));
Utility.FileOpation.Delete(newpath);
Utility.FileOpation.Delete(serPath);
var str = MongoHelper.ToBson(data);
File.WriteAllBytes(newpath, str);
File.WriteAllBytes(serPath, str);
}
private void SerilizeSkillEvent(RootNode rootNode, SkillLogicConfig skillLogicConfig)
{
foreach (var port in rootNode.Ports)
{
if (port.IsConnected && port.IsOutput)
{
skillLogicConfig.skillEventDic = skillLogicConfig.skillEventDic ?? new Dictionary<SkillEventCondition, SkillOptionBase[]>();
foreach (var anotherPort in port.GetConnections())
{
SkillEventConditionNode node = anotherPort.node.As<SkillEventConditionNode>();
SkillOptionBase[] arr = SerilizeSkillOptions(node);
skillLogicConfig.skillEventDic.Add(node.condition, arr);
}
}
}
SkillOptionBase[] SerilizeSkillOptions(SkillEventConditionNode node)
{
List<SkillOptionBase> list = new List<SkillOptionBase>();
foreach (var port in node.Ports)
{
if (port.IsConnected && port.IsOutput)
{
foreach (var anotherPort in port.GetConnections())
{
SkillOptionBase skillOption = System.Activator.CreateInstance(anotherPort.node.GetType()) as SkillOptionBase;
var anotherNode = anotherPort.node.As<SkillOptionBase>();
anotherNode.Clear();
anotherNode.DeepClone(skillOption);
anotherNode.Serilize(skillOption);
list.Add(skillOption);
}
}
}
return list.ToArray();
}
}
private void SerilizeModifier(SkillNodeGraph skillNodeGraph, SkillLogicConfig skillLogicConfig)
{
foreach (SkillNode node in skillNodeGraph.nodes)
{
if (node is ModifierNode modifierNode)
{
skillLogicConfig.modifierDic = skillLogicConfig.modifierDic ?? new Dictionary<ModifierId, ModifierConfig>();
var modifier = modifierNode.modifier.Clone();
skillLogicConfig.modifierDic.Add(modifier.Id, modifier);
SerilizeModifierEvent(modifierNode, modifier);
}
}
}
private void SerilizeModifierEvent(ModifierNode modifierNode, ModifierConfig modifier)
{
foreach (var port in modifierNode.Ports)
{
if (port.IsConnected && port.IsOutput)
{
modifier.modifierEventDic = modifier.modifierEventDic ?? new Dictionary<ModifierEventCondition, SkillOptionBase[]>();
foreach (var anotherPort in port.GetConnections())
{
ModifierEventConditionNode node = anotherPort.node.As<ModifierEventConditionNode>();
SkillOptionBase[] arr = SerilizeSkillOptions(node);
if (modifier.modifierEventDic.ContainsKey(node.condition))
{
Log.Error($"{node.uniqeId} {modifierNode.skillGraph.name}");
}
modifier.modifierEventDic.Add(node.condition, arr);
}
}
}
SkillOptionBase[] SerilizeSkillOptions(ModifierEventConditionNode node)
{
List<SkillOptionBase> list = new List<SkillOptionBase>();
foreach (var port in node.Ports)
{
if (port.IsConnected && port.IsOutput)
{
foreach (var anotherPort in port.GetConnections())
{
SkillOptionBase skillOption = System.Activator.CreateInstance(anotherPort.node.GetType()) as SkillOptionBase;
var anotherNode = anotherPort.node.As<SkillOptionBase>();
anotherNode.DeepClone(skillOption);
anotherNode.Clear();
anotherNode.Serilize(skillOption);
list.Add(skillOption);
}
}
}
return list.ToArray();
}
}
#endregion
private void GenerateNestIds(SkillNode node)
{
if (node == null) return;
//node.CheckData();
node.nextIds?.Clear();
foreach (var port in node.Ports)
{
if (port.IsConnected && port.IsOutput)
{
foreach (var otherPort in port.GetConnections())
{
node.nextIds = node.nextIds ?? new Dictionary<string, List<int>>();
if (!node.nextIds.TryGetValue(port.fieldName, out var list))
list = new List<int>();
list.Add(otherPort.node.As<SkillNode>().uniqeId);
node.nextIds[port.fieldName] = list;
}
}
}
}
#region Deserialize
[Button("加载")]
[ButtonGroup]
void LoadTxt()
{
RegisterMongo();
string path = Path.Combine(saveSODataDir, $"nodes.json");
string str = File.ReadAllText(path);
NodeDataUtil.dic = MongoHelper.FromJson<Dictionary<int, SkillNodeGraph>>(str);
Log.Info($"Load{DateTime.Now:MM_dd+HH_mm_ss} {str.Length / 1024f:f1}K");
}
[Button("反序列化")]
[ButtonGroup]
void Deserilize()
{
try
{
var arr = GetSkills();
foreach (var _skillNodeGraph in arr)
{
if (!NodeDataUtil.dic.TryGetValue(_skillNodeGraph.Id, out var deserilizedGraph))
{
return;
}
try
{
foreach (SkillNode node in deserilizedGraph.nodes)
{
try
{
SkillNode oldNode = _skillNodeGraph.nodes.Find(t => t.As<SkillNode>().uniqeId == node.uniqeId) as SkillNode;
if (oldNode == null)
{
GeanerateNotExistNode(_skillNodeGraph, deserilizedGraph.nodes.Find(t => t.As<SkillNode>().uniqeId == node.uniqeId) as SkillNode, node.uniqeId);
}
}
catch (Exception)
{
Log.Error($"[1]skill has error in dic which id = {_skillNodeGraph.Id}");
throw;
}
}
}
catch (Exception)
{
Log.Error($"[2]skill has error in dic which id = {_skillNodeGraph.Id}");
throw;
}
foreach (SkillNode node in deserilizedGraph.nodes)
{
SkillNode oldNode = _skillNodeGraph.nodes.Find(t => t.As<SkillNode>().uniqeId == node.uniqeId) as SkillNode;
if (oldNode == null)
{
Log.Error($"oldNode == null where id = {node.uniqeId}");
continue;
}
try
{
switch (oldNode)
{
default:
break;
case RootNode rootNode:
rootNode.skillLogic = node.As<RootNode>().skillLogic;
break;
case SkillEventConditionNode rootNode:
rootNode.condition = node.As<SkillEventConditionNode>().condition;
break;
case ModifierNode rootNode:
rootNode.modifier = node.As<ModifierNode>().modifier;
break;
case ModifierEventConditionNode rootNode:
rootNode.condition = node.As<ModifierEventConditionNode>().condition;
break;
case SkillOptionBase rootNode:
int index = _skillNodeGraph.nodes.IndexOf(oldNode);
_skillNodeGraph.nodes[index] = oldNode = node.As<SkillOptionBase>().Clone(rootNode);
break;
}
}
catch (Exception e)
{
Log.Error($"[3]skill has error in dic which id = {_skillNodeGraph.Id}");
Log.Error(e);
}
oldNode.position = node.position;
if (node.nextIds != null)
foreach (var kv in node.nextIds)
{
var outPut = oldNode.GetOutputPort(kv.Key);
outPut.ClearConnections();
foreach (var uniqeId in kv.Value)
{
SkillNode targetNode = _skillNodeGraph.GetNode(uniqeId);
if (targetNode == null)
{
Log.Error($"this is wrong when id = {uniqeId}");
targetNode = GeanerateNotExistNode(_skillNodeGraph, deserilizedGraph.nodes.Find(t => t.As<SkillNode>().uniqeId == uniqeId) as SkillNode, uniqeId);
}
outPut.Connect(targetNode.GetInputPort("input"));
}
}
}
EditorUtility.SetDirty(_skillNodeGraph);
}
Log.Info($"反序列化成功 {DateTime.Now:MM_dd+HH_mm_ss}");
}
catch (Exception e)
{
Log.Info($"反序列化失败 {DateTime.Now:MM_dd+HH_mm_ss}");
Log.Error($"{e}");
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private SkillNode GeanerateNotExistNode(SkillNodeGraph skillGraph, SkillNode skillNode, int uniqeId)
{
SkillNode node = skillGraph.AddNodeWithId(skillNode.GetType(), uniqeId) as SkillNode;
switch (node)
{
default:
break;
case RootNode rootNode:
rootNode.skillLogic = skillNode.As<RootNode>().skillLogic;
break;
case SkillEventConditionNode rootNode:
rootNode.condition = skillNode.As<SkillEventConditionNode>().condition;
break;
case ModifierNode rootNode:
rootNode.modifier = skillNode.As<ModifierNode>().modifier;
break;
case ModifierEventConditionNode rootNode:
rootNode.condition = skillNode.As<ModifierEventConditionNode>().condition;
break;
case SkillOptionBase rootNode:
int index = skillGraph.nodes.IndexOf(node);
node.position = skillNode.position;
skillGraph.nodes[index] = node = skillNode.As<SkillOptionBase>().Clone(rootNode);
break;
}
node.name = skillNode.name;
AssetDatabase.AddObjectToAsset(node, skillGraph);
return node;
}
#endregion
public static void RegisterMongo()
{
try
{
BsonSerializer.RegisterSerializer(typeof(ModifierId), new StructBsonSerialize<ModifierId>());
BsonSerializer.RegisterSerializer(typeof(CastParam), new StructBsonSerialize<CastParam>());
}
catch (Exception e)
{
Log.Error(e);
}
Type[] types = typeof(RootNode).Assembly.GetTypes();
foreach (Type type in types)
{
if (!type.IsSubclassOf(typeof(SelectTargetBase)) &&
!type.IsSubclassOf(typeof(SkillNode)) &&
!type.IsSubclassOf(typeof(Node)) &&
!type.IsSubclassOf(typeof(NodeGraph)) &&
!type.IsSubclassOf(typeof(SkillOptionBase))
)
{
continue;
}
if (type.IsGenericType)
{
continue;
}
try
{
MongoDB.Bson.Serialization.BsonClassMap.LookupClassMap(type);
}
catch (Exception e)
{
Log.Error($"11: {type.Name} {e}");
}
}
}
}