/// <summary>
 /// 处理proto文件
 /// </summary>
 /// <param name="protoPath">proto路径</param>
 /// <param name="decodeOutputPath">转换脚本导出路径,默认与proto同路径,后缀名为".lua"</param>
 /// <param name="adjustOutputPath">调整脚本导出路径,默认与proto同路径,后缀为"_adj.lua"</param>
 /// <param name="needCheckCSharpType">是否需要检查C#类型是否存在</param>
 /// <returns>是否有lua文件生成</returns>
 public bool DealProto(string protoPath, string decodeOutputPath = null, string adjustOutputPath = null, bool needCheckCSharpType = false)
 {
     if (string.IsNullOrEmpty(protoPath))
     {
         return(false);
     }
     ClearCache();
     //生成转换代码
     if (string.IsNullOrEmpty(decodeOutputPath))
     {
         decodeOutputPath = Path.ChangeExtension(protoPath, ".lua");
     }
     decodeOutputFilePath = decodeOutputPath;
     proto = ProtocolControlCache_ProtoStructure.GetProtoStructure(protoPath);
     if (proto == null || (proto != null && string.IsNullOrEmpty(proto.Package)))
     {
         ClearCache();
         return(false);
     }
     else
     {
         GenerateDecodeLuaCodes(needCheckCSharpType);
         if (!SaveLuaCodes(decodeOutputFilePath))
         {
             ClearCache();
             return(false);
         }
         ClearCache();
     }
     //生成调整代码
     if (string.IsNullOrEmpty(adjustOutputPath))
     {
         adjustOutputPath = Path.ChangeExtension(protoPath, ".lua");
         adjustOutputPath = adjustOutputPath.Substring(0, adjustOutputPath.Length - 4) + "_adj.lua";
     }
     adjustOutputFilePath = adjustOutputPath;
     proto = ProtocolControlCache_ProtoStructure.GetProtoStructure(protoPath);
     if (proto == null || (proto != null && string.IsNullOrEmpty(proto.Package)))
     {
         ClearCache();
         return(false);
     }
     else
     {
         GenerateAdjustLuaCodes(false);
         if (!SaveLuaCodes(adjustOutputFilePath))
         {
             ClearCache();
             return(false);
         }
         ClearCache();
         return(true);
     }
 }
 /// <summary>
 /// 清理缓存
 /// </summary>
 private void ClearCache()
 {
     decodeOutputFilePath = null;
     adjustOutputFilePath = null;
     proto = null;
     cacheStringBuilder.Remove(0, cacheStringBuilder.Length);
     stringBuilderForRetract.Remove(0, stringBuilderForRetract.Length);
     stringBuilderForMessage.Remove(0, stringBuilderForMessage.Length);
     stringBuilderForVariable.Remove(0, stringBuilderForVariable.Length);
     retractCount          = 0;
     isAnyMessageGenerated = false;
 }
Пример #3
0
 /// <summary>
 /// 从协议的消息结构得到其使用的proto的数据结构,若返回null则表明该消息未使用proto
 /// </summary>
 /// <param name="msg"></param>
 /// <returns></returns>
 public static ProtocolControlCache_ProtoStructure GetProtoStructure(ProtocolControlCache_Message msg)
 {
     if (msg != null)
     {
         if (msg.hasProto)
         {
             string path = string.Format("{0}/{1}.proto", LocalServerProtoPath, msg.protoData.protoName);
             ProtocolControlCache_ProtoStructure protoStructure = ProtocolControlCache_ProtoStructure.GetProtoStructure(path);
             return(protoStructure);
         }
     }
     return(null);
 }
Пример #4
0
    /// <summary>
    /// 获取proto结构
    /// </summary>
    /// <param name="fullPath"></param>
    /// <returns></returns>
    public static ProtocolControlCache_ProtoStructure GetProtoStructure(string fullPath)
    {
        if (string.IsNullOrEmpty(fullPath))
        {
            return(null);
        }
        if (ProtocolStructureCache.ContainsKey(fullPath))
        {
            return(ProtocolStructureCache[fullPath]);
        }
        var temp = new ProtocolControlCache_ProtoStructure(fullPath);

        ProtocolStructureCache[fullPath] = temp;
        temp.Deal();
        return(temp);
    }
Пример #5
0
    /// <summary>
    /// 更新Lua提示文件
    /// </summary>
    /// <param name="protoFolderPath">proto文件夹路径</param>
    /// <param name="luaRefrenceFileName">lua引用文件名</param>
    /// <param name="isCommitToSVN">是否生成后提交svn</param>
    public static void UpdateLuaHintFile(string protoFolderPath, string luaRefrenceFileName, bool isCommitToSVN)
    {
        if (!Directory.Exists(protoFolderPath))
        {
            UnityEngine.Debug.LogErrorFormat("未找到 {0} 文件夹", protoFolderPath);
            return;
        }
        string luaRefrenceOutputPath = ProtoHintFolderPath;

        if (!Directory.Exists(luaRefrenceOutputPath))
        {
            Directory.CreateDirectory(luaRefrenceOutputPath);
        }
        string[]      files         = Directory.GetFiles(protoFolderPath);
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < files.Length; i++)
        {
            EditorUtility.DisplayProgressBar("解析proto结构", files[i], ((float)i) / files.Length);
            var protoStructure = ProtocolControlCache_ProtoStructure.GetProtoStructure(files[i]);
            EditorUtility.DisplayProgressBar("生成proto提示文件", files[i], ((float)i) / files.Length);
            for (int j = 0; j < protoStructure.Messages.Count; j++)
            {
                stringBuilder.Append(GenerateLuaClassHint(protoStructure, protoStructure.Messages[j]));
                stringBuilder.Append("\r\n\r\n");
            }
        }
        EditorUtility.ClearProgressBar();
        string outputFilePath = luaRefrenceOutputPath + "/" + luaRefrenceFileName;

        File.WriteAllText(outputFilePath, stringBuilder.ToString());
        UnityEngine.Debug.LogFormat("{0} 生成完毕,idea中可以引用该文件或者其所在文件夹", outputFilePath);
        if (isCommitToSVN)
        {
            //SVNEditorUtility.SVNCommit(luaRefrenceOutputPath);
        }
    }
Пример #6
0
    /// <summary>
    /// 生成lua类的提示
    /// </summary>
    /// <param name="proto"></param>
    /// <param name="msg"></param>
    /// <returns></returns>
    public static string GenerateLuaClassHint(ProtocolControlCache_ProtoStructure proto, ProtocolControlCache_ProtoStructure.Message msg)
    {
        if (msg == null)
        {
            return(string.Empty);
        }
        stringBuilderForLuaClassHint.Remove(0, stringBuilderForLuaClassHint.Length);
        stringBuilderForLuaClassHint.Append("---@class ");
        stringBuilderForLuaClassHint.Append(proto.Package);
        stringBuilderForLuaClassHint.Append(".");
        stringBuilderForLuaClassHint.Append(msg.MessageName);
        stringBuilderForLuaClassHint.Append("\r\n");
        stringBuilderForLuaClassHint.Append("---class properties");
        stringBuilderForLuaClassHint.Append("\r\n");
        for (int i = 0; i < msg.Variables.Length; i++)
        {
            var    variable = msg.Variables[i];
            string typeStr  = null;
            switch (variable.VType)
            {
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Bool:
                typeStr = "boolean";
                break;

            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Double:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Float:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Int32:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.UInt32:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Int64:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.UInt64:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.SInt32:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.SInt64:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Sing64:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Fixed32:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Fixed64:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.SFixed32:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.SFixed64:
                typeStr = "number";
                break;

            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.String:
            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Bytes:
                typeStr = "string";
                break;

            case ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Others:
                ServerTool_ProtocolController_GenerateLuaFromProto.VariableTypeInOthers variableTypeInOthers = ServerTool_ProtocolController_GenerateLuaFromProto.GetVariableTypeInOthers(proto, msg, variable);
                if (variableTypeInOthers.isEnumType && variableTypeInOthers.enumType != null)
                {
                    typeStr = "number";
                }
                else
                {
                    typeStr = variableTypeInOthers.typeString;
                }
                break;

            default:
                break;
            }
            switch (variable.Modifier)
            {
            case ProtocolControlCache_ProtoStructure.VariableInMessage.ModifierType.Required:
                stringBuilderForLuaClassHint.Append("---@field public ");
                stringBuilderForLuaClassHint.Append(variable.VariableName);
                stringBuilderForLuaClassHint.Append(" ");
                stringBuilderForLuaClassHint.Append(typeStr);
                if (!string.IsNullOrEmpty(variable.DefaultValue))
                {
                    stringBuilderForLuaClassHint.Append(" [default = ");
                    stringBuilderForLuaClassHint.Append(variable.DefaultValue);
                    stringBuilderForLuaClassHint.Append("]");
                }
                if (!string.IsNullOrEmpty(variable.Comment))
                {
                    stringBuilderForLuaClassHint.Append(" ");
                    stringBuilderForLuaClassHint.Append(variable.Comment.Replace("\n", " ").Replace("\r", ""));
                }
                stringBuilderForLuaClassHint.Append("\r\n");
                break;

            case ProtocolControlCache_ProtoStructure.VariableInMessage.ModifierType.Optional:
                stringBuilderForLuaClassHint.Append("---@field public ");
                stringBuilderForLuaClassHint.Append(variable.VariableName);
                stringBuilderForLuaClassHint.Append(" ");
                stringBuilderForLuaClassHint.Append(typeStr);
                if (!string.IsNullOrEmpty(variable.DefaultValue))
                {
                    stringBuilderForLuaClassHint.Append(" [default = ");
                    stringBuilderForLuaClassHint.Append(variable.DefaultValue);
                    stringBuilderForLuaClassHint.Append("]");
                }
                if (!string.IsNullOrEmpty(variable.Comment))
                {
                    stringBuilderForLuaClassHint.Append(" ");
                    stringBuilderForLuaClassHint.Append(variable.Comment.Replace("\n", " ").Replace("\r", ""));
                }
                stringBuilderForLuaClassHint.Append("\r\n");
                stringBuilderForLuaClassHint.Append("---@field public ");
                stringBuilderForLuaClassHint.Append(variable.VariableName);
                stringBuilderForLuaClassHint.Append("Specified boolean");
                stringBuilderForLuaClassHint.Append("\r\n");
                break;

            case ProtocolControlCache_ProtoStructure.VariableInMessage.ModifierType.Repeated:
                stringBuilderForLuaClassHint.Append("---@field public ");
                stringBuilderForLuaClassHint.Append(variable.VariableName);
                stringBuilderForLuaClassHint.Append(" table<number, ");
                stringBuilderForLuaClassHint.Append(typeStr);
                stringBuilderForLuaClassHint.Append(">");
                if (!string.IsNullOrEmpty(variable.Comment))
                {
                    stringBuilderForLuaClassHint.Append(" ");
                    stringBuilderForLuaClassHint.Append(variable.Comment.Replace("\n", " ").Replace("\r", ""));
                }
                stringBuilderForLuaClassHint.Append("\r\n");
                break;

            case ProtocolControlCache_ProtoStructure.VariableInMessage.ModifierType.NULL:
                break;

            default:
                break;
            }
        }
        return(stringBuilderForLuaClassHint.ToString());
    }
Пример #7
0
    public void Deal()
    {
        try
        {
            protoContent = File.ReadAllText(protoFullPath);
        }
        catch (FileNotFoundException ex)
        {
            UnityEngine.Debug.LogError(string.Format("读取proto文件错误,文件路径无效 {0}\r\n{1}\r\n{2}", protoFullPath, ex.Message, ex.StackTrace));
            return;
        }
        catch (DirectoryNotFoundException ex)
        {
            UnityEngine.Debug.LogError(string.Format("读取proto文件错误,目录无效 {0}\r\n{1}\r\n{2}", protoFullPath, ex.Message, ex.StackTrace));
            return;
        }
        catch (IOException ex)
        {
            UnityEngine.Debug.LogError(string.Format("读取proto文件错误,文件IO被占用 {0}\r\n{1}\r\n{2}", protoFullPath, ex.Message, ex.StackTrace));
            return;
        }
        catch (Exception ex)
        {
            UnityEngine.Debug.LogError(string.Format("读取proto文件错误 {0}\r\n{1}\r\n{2}", protoFullPath, ex.Message, ex.StackTrace));
            return;
        }
        Match packageMatch = Regex.Match(protoContent, pattern_Package);

        if (packageMatch != null)
        {
            string strTemp = packageMatch.Value;
            package = strTemp.Replace("package ", string.Empty).Replace(';', ' ').Trim();
        }
        MatchCollection importedProtoMatchCollection = Regex.Matches(protoContent, pattern_ImportProto);

        if (importedProtoMatchCollection != null)
        {
            foreach (Match item in importedProtoMatchCollection)
            {
                string newProtoName = item.Value.Replace("import", string.Empty).Replace('\"', ' ').Replace(';', ' ').Replace(".proto", string.Empty).Trim();
                string dirPath      = Path.GetDirectoryName(protoFullPath);
                ProtocolControlCache_ProtoStructure importedProtoTemp = GetProtoStructure(dirPath + '/' + newProtoName + ".proto");
                ImportedProtos.Add(importedProtoTemp);
            }
        }
        MatchCollection messageMatchCollection = Regex.Matches(protoContent, Message.pattern);

        if (messageMatchCollection != null)
        {
            foreach (Match item in messageMatchCollection)
            {
                Message message = new Message(item.Value);
                message.Owner = this;
                if (message.Deal())
                {
                    Messages.Add(message);
                }
            }
        }
        MatchCollection enumMatchCollection = Regex.Matches(protoContent, EnumType.pattern);

        if (enumMatchCollection != null)
        {
            //将所有message中的枚举名放到一起
            List <EnumType> enumnames = new List <EnumType>();
            for (int i = 0; i < Messages.Count; i++)
            {
                for (int j = 0; j < Messages[i].Enums.Length; j++)
                {
                    enumnames.Add(Messages[i].Enums[j]);
                }
            }
            //遍历proto中所有的枚举,若message中没有相同的枚举,则将其加入列表中
            foreach (Match item in enumMatchCollection)
            {
                EnumType enumtemp = new EnumType(item.Value);
                if (enumtemp.Deal())
                {
                    bool isContain = false;
                    for (int i = 0; i < enumnames.Count; i++)
                    {
                        if (enumnames[i].IsEqualTo(enumtemp))
                        {
                            enumnames.RemoveAt(i);
                            isContain = true;
                            break;
                        }
                    }
                    if (!isContain)
                    {
                        EnumsInProto.Add(enumtemp);
                    }
                }
            }
        }
        protoContent = string.Empty;
    }
    /// <summary>
    /// 获得变量类型为Others的变量的实际类型
    /// </summary>
    /// <param name="proto">消息所属的proto</param>
    /// <param name="msg">变量所在消息</param>
    /// <param name="variable">需要获取类型的变量</param>
    /// <returns>其他类型变量的类型</returns>
    public static VariableTypeInOthers GetVariableTypeInOthers(ProtocolControlCache_ProtoStructure proto, ProtocolControlCache_ProtoStructure.Message msg, ProtocolControlCache_ProtoStructure.VariableInMessage variable)
    {
        VariableTypeInOthers variableTypeInOthers = new VariableTypeInOthers();

        //Others一般只有枚举和消息两种类型,多层次遍历查询
        //得到去掉包名或者消息名的变量类型名
        string[] strs = variable.VariableTypeString.Split('.');
        string   pureVariableTypeString;

        if (strs != null && strs.Length > 1)
        {
            pureVariableTypeString = strs[strs.Length - 1];
        }
        else
        {
            pureVariableTypeString = variable.VariableTypeString;
        }
        //先遍历本消息内定义的枚举
        for (int i = 0; i < msg.Enums.Length; i++)
        {
            if (pureVariableTypeString == msg.Enums[i].EnumName)
            {
                variableTypeInOthers.isEnumType             = true;
                variableTypeInOthers.isInOtherPackage       = false;
                variableTypeInOthers.decodeHelpString       = string.Format("CS.{0}.{1}.{2}.__CastFrom", proto.Package, msg.MessageName, msg.Enums[i].EnumName);
                variableTypeInOthers.typeString             = string.Format("{0}.{1}.{2}", proto.Package, msg.MessageName, msg.Enums[i].EnumName);
                variableTypeInOthers.adjustHelpString       = string.Empty;
                variableTypeInOthers.adjustNullAdjustString = string.Empty;
                variableTypeInOthers.enumType    = msg.Enums[i];
                variableTypeInOthers.messageType = null;
                return(variableTypeInOthers);
            }
        }
        //再遍历本proto中定义的枚举
        for (int i = 0; i < proto.EnumsInProto.Count; i++)
        {
            if (pureVariableTypeString == proto.EnumsInProto[i].EnumName)
            {
                variableTypeInOthers.isEnumType             = true;
                variableTypeInOthers.isInOtherPackage       = false;
                variableTypeInOthers.decodeHelpString       = string.Format("CS.{0}.{1}.__CastFrom", proto.Package, proto.EnumsInProto[i].EnumName);
                variableTypeInOthers.typeString             = string.Format("{0}.{1}", proto.Package, proto.EnumsInProto[i].EnumName);
                variableTypeInOthers.adjustNullAdjustString = string.Empty;
                variableTypeInOthers.adjustHelpString       = string.Empty;
                variableTypeInOthers.enumType    = proto.EnumsInProto[i];
                variableTypeInOthers.messageType = null;
                return(variableTypeInOthers);
            }
        }
        //而后遍历proto中定义的消息
        for (int i = 0; i < proto.Messages.Count; i++)
        {
            if (pureVariableTypeString == proto.Messages[i].MessageName)
            {
                variableTypeInOthers.isEnumType             = false;
                variableTypeInOthers.isInOtherPackage       = false;
                variableTypeInOthers.decodeHelpString       = string.Format("{0}.{1}", proto.Package, proto.Messages[i].MessageName);
                variableTypeInOthers.typeString             = string.Format("{0}.{1}", proto.Package, proto.Messages[i].MessageName);
                variableTypeInOthers.adjustHelpString       = string.Format("{0}_adj.Adjust{1}", proto.Package, proto.Messages[i].MessageName);
                variableTypeInOthers.adjustNullAdjustString = string.Format("{0}_adj.Adjust{1} ~= nil", proto.Package, proto.Messages[i].MessageName);
                variableTypeInOthers.enumType    = null;
                variableTypeInOthers.messageType = proto.Messages[i];
                return(variableTypeInOthers);
            }
        }
        //最后遍历其他proto
        for (int i = 0; i < proto.ImportedProtos.Count; i++)
        {
            //枚举
            for (int j = 0; j < proto.ImportedProtos[i].EnumsInProto.Count; j++)
            {
                if (pureVariableTypeString == proto.ImportedProtos[i].EnumsInProto[j].EnumName)
                {
                    variableTypeInOthers.isEnumType             = true;
                    variableTypeInOthers.isInOtherPackage       = true;
                    variableTypeInOthers.decodeHelpString       = string.Format("CS.{0}.{1}.__CastFrom", proto.ImportedProtos[i].Package, proto.ImportedProtos[i].EnumsInProto[j].EnumName);
                    variableTypeInOthers.typeString             = string.Format("{0}.{1}", proto.ImportedProtos[i].Package, proto.ImportedProtos[i].EnumsInProto[j].EnumName);
                    variableTypeInOthers.adjustHelpString       = string.Empty;
                    variableTypeInOthers.adjustNullAdjustString = string.Empty;
                    variableTypeInOthers.enumType    = proto.ImportedProtos[i].EnumsInProto[j];
                    variableTypeInOthers.messageType = null;
                    return(variableTypeInOthers);
                }
            }
            //消息
            for (int j = 0; j < proto.ImportedProtos[i].Messages.Count; j++)
            {
                if (pureVariableTypeString == proto.ImportedProtos[i].Messages[j].MessageName)
                {
                    variableTypeInOthers.isEnumType             = false;
                    variableTypeInOthers.isInOtherPackage       = true;
                    variableTypeInOthers.decodeHelpString       = string.Format("decodeTable.{0}.{1}", proto.ImportedProtos[i].ProtoFileName, proto.ImportedProtos[i].Messages[j].MessageName);
                    variableTypeInOthers.typeString             = string.Format("{0}.{1}", proto.ImportedProtos[i].Package, proto.ImportedProtos[i].Messages[j].MessageName);
                    variableTypeInOthers.adjustHelpString       = string.Format("adjustTable.{0}_adj.Adjust{1}", proto.ImportedProtos[i].ProtoFileName, proto.ImportedProtos[i].Messages[j].MessageName);
                    variableTypeInOthers.adjustNullAdjustString = string.Format("adjustTable.{0}_adj ~= nil and adjustTable.{0}_adj.Adjust{1} ~= nil", proto.ImportedProtos[i].ProtoFileName, proto.ImportedProtos[i].Messages[j].MessageName);
                    variableTypeInOthers.enumType    = null;
                    variableTypeInOthers.messageType = proto.ImportedProtos[i].Messages[j];
                    return(variableTypeInOthers);
                }
            }
        }
        //若还未找到,则返回原始的变量类型
        variableTypeInOthers.isEnumType             = false;
        variableTypeInOthers.isInOtherPackage       = false;
        variableTypeInOthers.decodeHelpString       = variable.VariableTypeString;
        variableTypeInOthers.typeString             = variable.VariableTypeString;
        variableTypeInOthers.adjustHelpString       = variable.VariableTypeString;
        variableTypeInOthers.adjustNullAdjustString = variable.VariableTypeString;
        variableTypeInOthers.enumType    = null;
        variableTypeInOthers.messageType = null;
        if (variable.VType == ProtocolControlCache_ProtoStructure.VariableInMessage.VariableType.Others)
        {
            UnityEngine.Debug.LogErrorFormat("未在proto文件或其他proto文件中找到 {0}.{1} 的 {2} 字段类型", proto.Package, msg.MessageName, variable.VariableTypeString);
        }
        return(variableTypeInOthers);
    }
Пример #9
0
 /// <summary>
 /// 初始化,后续代码在此添加
 /// </summary>
 public void Initialize()
 {
     ProtocolControlCache_ProtoStructure.ClearProtoStructureCache();
 }
Пример #10
0
 private static void OnScriptCompileFinished()
 {
     ProtocolControlCache_ProtoStructure.ClearProtoStructureCache();
 }