当前位置: 首页 > news >正文

Unity网络开发--自定义协议生成工具

根据配置文件自动生成枚举类,数据结构类,消息类

using System.Collections;
using System.Collections.Generic;
using System.Xml;
using UnityEditor;
using UnityEngine;public class ProtocolTool 
{private static string PROTO_INFO_PATH = Application.dataPath + "/Editor/ProtocolTool/Protocollnfo.xml";private static GenerateCSharp generateCSharp = new GenerateCSharp();[MenuItem("ProtocolTool/生成C#脚本")]private static void GenerateCSharp(){//读取xml相关信息generateCSharp.GenerateEnum(GetNodes("enum"));generateCSharp.GenerateData(GetNodes("data"));AssetDatabase.Refresh();}private static XmlNodeList GetNodes(string nodeName){XmlDocument xml = new XmlDocument();xml.Load(PROTO_INFO_PATH);XmlNode root = xml.SelectSingleNode("messages");return root.SelectNodes(nodeName);}
}
using PlasticGui.WorkspaceWindow.Diff;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEngine;public class GenerateCSharp
{private string SAVE_PATH = Application.dataPath + "/Scripts/Protocol/";//生成枚举public void GenerateEnum(XmlNodeList xmlNodeList){string namespaseStr = "";string enumNameStr = "";string fieldStr = "";foreach (XmlNode enumNode in xmlNodeList){namespaseStr = enumNode.Attributes["namespace"].Value;enumNameStr = enumNode.Attributes["name"].Value;fieldStr = "";XmlNodeList enumFields = enumNode.SelectNodes("field");foreach (XmlNode enumField in enumFields){fieldStr += "\t\t" + enumField.Attributes["name"].Value;if (enumField.InnerText != "")fieldStr += " = " + enumField.InnerText;fieldStr += ",\r\n";}string enumStr = $"namespace {namespaseStr}\r\n" +"{\r\n" +$"\tpublic enum {enumNameStr}\r\n" +"\t{\r\n" +fieldStr +"\t}\r\n" +"}\r\n";string path = SAVE_PATH + namespaseStr + "/Enum/";if (!Directory.Exists(path))Directory.CreateDirectory(path);File.WriteAllText(path + enumNameStr + ".cs", enumStr);}Debug.Log("枚举生成结束");}//生成数据结构类public void GenerateData(XmlNodeList xmlNodeList){string namespaceStr = "";string classNameStr = "";string fieldStr = "";string getBytesNumStr = "";string writingStr = "";string readingStr = "";foreach (XmlNode dataNode in xmlNodeList){namespaceStr = dataNode.Attributes["namespace"].Value;classNameStr = dataNode.Attributes["name"].Value;XmlNodeList nodeList = dataNode.SelectNodes("field");fieldStr = GetFieldStr(nodeList);getBytesNumStr = GetGetBytesNumStr(nodeList);writingStr = GetWritingStr(nodeList);readingStr = GetReadingStr(nodeList);string dataStr = "using System;\r\n" +"using System.Text;\r\n" +"using System.Collections.Generic;\r\n\r\n\r\n" +$"namespace {namespaceStr}\r\n" +"{\r\n" +$"\tpublic class {classNameStr} : BaseData\r\n" +"\t{\r\n" +fieldStr +"\r\n\r\n\r\n" +"\t\tpublic override int GetBytesNum()\r\n" +"\t\t{\r\n" +"   \t\t\tint num = 0;\r\n" +$"{getBytesNumStr}\r\n" +"\t\t\treturn num;\r\n" +"\t\t}\r\n\r\n" +"\t\tpublic override byte[] Writing()\r\n" +"\t\t{\r\n" +"\t\t\t int index = 0;\r\n" +"\t\t\t byte[] bytes = new byte[GetBytesNum()];\r\n" +$"{writingStr}\r\n" +"\t\t\treturn bytes;\r\n" +"\t\t}\r\n" +"\t\tpublic override int Reading(byte[] bytes, int beginIndex)\r\n" +"\t\t{\r\n" +"\t\t\tint index = beginIndex;\r\n" +$"{readingStr}\r\n" +"\t\t\treturn index -beginIndex;\r\n" +"\t\t}\r\n\r\n" +"\t}\r\n" +"}";string path = SAVE_PATH + namespaceStr + "/Data/";if (!Directory.Exists(path))Directory.CreateDirectory(path);File.WriteAllText(path + classNameStr + ".cs", dataStr);}Debug.Log("数据结构类生成结束");}//生成消息public void GenerateDataMsg(XmlNodeList xmlNodeList){string namespaceStr = "";string classNameStr = "";string fieldStr = "";string getBytesNumStr = "";string writingStr = "";string readingStr = "";foreach (XmlNode dataNode in xmlNodeList){namespaceStr = dataNode.Attributes["namespace"].Value;classNameStr = dataNode.Attributes["name"].Value;XmlNodeList nodeList = dataNode.SelectNodes("field");fieldStr = GetFieldStr(nodeList);getBytesNumStr = GetGetBytesNumStr(nodeList);writingStr = GetWritingStr(nodeList);readingStr = GetReadingStr(nodeList);string dataStr = "using System;\r\n" +"using System.Text;\r\n" +"using System.Collections.Generic;\r\n\r\n\r\n" +$"namespace {namespaceStr}\r\n" +"{\r\n" +$"\tpublic class {classNameStr} : BaseMsg\r\n" +"\t{\r\n" +fieldStr +"\r\n\r\n\r\n" +"\t\tpublic override int GetID()\r\n" +"\t\t{\r\n"+$"\t\t\treturn {dataNode.Attributes["id"].Value};\r\n"+"\t\t}\r\n\r\n" +"\t\tpublic override int GetBytesNum()\r\n" +"\t\t{\r\n" +"   \t\t\tint num = 0;\r\n" +$"{getBytesNumStr}\r\n" +"\t\t\treturn num;\r\n" +"\t\t}\r\n\r\n" +"\t\tpublic override byte[] Writing()\r\n" +"\t\t{\r\n" +"\t\t\t int index = 0;\r\n" +"\t\t\t byte[] bytes = new byte[GetBytesNum()];\r\n" +"\t\t\t WriteInt(bytes, GetID(), ref index);\r\n"+"\t\t\t WriteInt(bytes, GetBytesNum() - 8, ref index);\r\n" +$"{writingStr}\r\n" +"\t\t\treturn bytes;\r\n" +"\t\t}\r\n" +"\t\tpublic override int Reading(byte[] bytes, int beginIndex)\r\n" +"\t\t{\r\n" +"\t\t\tint index = beginIndex;\r\n" +$"{readingStr}\r\n" +"\t\t\treturn index -beginIndex;\r\n" +"\t\t}\r\n\r\n" +"\t}\r\n" +"}";string path = SAVE_PATH + namespaceStr + "/DataMsg/";if (!Directory.Exists(path))Directory.CreateDirectory(path);File.WriteAllText(path + classNameStr + ".cs", dataStr);}Debug.Log("数据结构类生成结束");}/// <summary>/// 获取成员变量声明内容/// </summary>/// <param name="fields"></param>/// <returns></returns>private string GetFieldStr(XmlNodeList fields){string fieldStr = "";foreach (XmlNode field in fields){string type = field.Attributes["type"].Value;string fieldName = field.Attributes["name"].Value;if (type == "list"){string T = field.Attributes["T"].Value;fieldStr += "\t\tpublic " + $"List<{T}> ";}else if (type == "array"){string T = field.Attributes["T"].Value;fieldStr += "\t\tpublic " + $"{T}[] ";}else if (type == "enum"){string T = field.Attributes["T"].Value;fieldStr += "\t\tpublic " + $"{T} ";}else if (type == "dic"){string Tkey = field.Attributes["Tkey"].Value;string Tvalue = field.Attributes["Tvalue"].Value;fieldStr += "\t\tpublic " + $"Dictionary<{Tkey},{Tvalue}> ";}else{fieldStr += "\t\tpublic " + type + " ";}fieldStr += fieldName + ";\r\n";}return fieldStr;}/// <summary>/// 拼接 GetBytesNum函数的方法/// </summary>/// <param name="fields"></param>/// <returns></returns>private string GetGetBytesNumStr(XmlNodeList fields){string bytesNumStr = "";string type = "";string name = "";foreach (XmlNode field in fields){type = field.Attributes["type"].Value;name = field.Attributes["name"].Value;if (type == "list"){string T = field.Attributes["T"].Value;bytesNumStr += "\t\t\tnum += 4;\r\n";bytesNumStr += $"\t\t\tfor (int i = 0; i < {name}.Count; i++)\r\n";bytesNumStr += $"\t\t\t\tnum += {GetValueBytesNum(T, name + "[i]")};\r\n";}else if (type == "array"){string T = field.Attributes["T"].Value;bytesNumStr += "\t\t\tnum += 4;\r\n";bytesNumStr += $"\t\t\tfor (int i = 0; i < {name}.Length; i++)\r\n";bytesNumStr += $"\t\t\t\tnum += {GetValueBytesNum(T, name + "[i]")};\r\n";}else if (type == "dic"){string Tkey = field.Attributes["Tkey"].Value;string Tvalue = field.Attributes["Tvalue"].Value;bytesNumStr += "\t\t\tnum += 4;\r\n";bytesNumStr += $"\t\t\tforeach ({Tkey} key in {name}.Keys)\r\n";bytesNumStr += "\t\t\t{\r\n";bytesNumStr += $"\t\t\t\tnum += {GetValueBytesNum(Tkey, "key")};\r\n";bytesNumStr += $"\t\t\t\tnum += " + GetValueBytesNum(Tvalue, name + "[key]") + ";\r\n";bytesNumStr += "\t\t\t}\r\n";}else{bytesNumStr += "\t\t\tnum += " + GetValueBytesNum(type, name) + ";\r\n";}}return bytesNumStr;}/// <summary>/// 获取指定类型的字节数/// </summary>/// <param name="type"></param>/// <param name="name"></param>/// <returns></returns>private string GetValueBytesNum(string type, string name){switch (type){case "long":return "8";case "int":case "float":case "enum":return "4";case "byte":case "bool":return "1";case "short":return "2";case "string":return "4 + Encoding.UTF8.GetByteCount(" + name + ")";default:return name + ".GetBytesNum()";}}/// <summary>/// 拼接Writing函数方法/// </summary>/// <param name="fields"></param>/// <returns></returns>private string GetWritingStr(XmlNodeList fields){string writingStr = "";string type = "";string name = "";foreach (XmlNode field in fields){type = field.Attributes["type"].Value;name = field.Attributes["name"].Value;if (type == "list"){string T = field.Attributes.GetNamedItem("T").Value;writingStr += "\t\t\t" + GetFieldWritingStr("int", $"{name}.Count") + "\r\n";writingStr += $"\t\t\tfor (int i = 0; i < {name}.Count; i++)\r\n";writingStr += "\t\t\t\t" + GetFieldWritingStr(T, $"{name}[i]") + "\r\n\r\n";}else if (type == "array"){string T = field.Attributes.GetNamedItem("T").Value;writingStr += "\t\t\t" + GetFieldWritingStr("int", $"{name}.Length") + "\r\n";writingStr += $"\t\t\tfor (int i = 0; i < {name}.Length; i++)\r\n";writingStr += "\t\t\t\t" + GetFieldWritingStr(T, $"{name}[i]") + "\r\n\r\n";}else if (type == "dic"){string Tkey = field.Attributes.GetNamedItem("Tkey").Value;string Tvalue = field.Attributes.GetNamedItem("Tvalue").Value;writingStr += "\t\t\t" + GetFieldWritingStr("int", $"{name}.Count") + "\r\n";writingStr += $"\t\t\tforeach({Tkey} key in {name}.Keys)\r\n";writingStr += "\t\t\t{\r\n";writingStr += $"\t\t\t\t" + GetFieldWritingStr(Tkey, "key") + "\r\n";writingStr += "\t\t\t\t" + GetFieldWritingStr(Tvalue, $"{name}[key]") + "\r\n";writingStr += "\t\t\t}\r\n\r\n";}else{writingStr += "\t\t\t" + GetFieldWritingStr(type, name) + "\r\n";}}return writingStr;}private string GetFieldWritingStr(string type, string name){switch (type){case "long":return $"WriteLong(bytes, {name}, ref index);";case "int":return $"WriteInt(bytes, {name}, ref index);";case "enum":return $"WriteInt(bytes, Convert.ToInt32({name}), ref index);";case "float":return $"WriteFloat(bytes, {name}, ref index);";case "byte":return $"WriteByte(bytes, {name}, ref index);";case "bool":return $"WriteBool(bytes, {name}, ref index);";case "short":return $"WriteShort(bytes, {name}, ref index);";case "string":return $"WriteString(bytes, {name}, ref index);";default:return $"WriteData(bytes, {name}, ref index);";}}/// <summary>/// 拼接Reading函数方法/// </summary>/// <param name="fields"></param>/// <returns></returns>private string GetReadingStr(XmlNodeList fields){string readingStr = "";readingStr += "\t\t\tint temp = 0;\r\n";string type = "";string name = "";foreach (XmlNode field in fields){type = field.Attributes["type"].Value;name = field.Attributes["name"].Value;if (type == "list"){ string T = field.Attributes["T"].Value;readingStr += "\t\t\ttemp = 0;\r\n";readingStr += "\t\t\ttemp = " + GetFieldReadingStr("int") + ";\r\n";readingStr += "\t\t\tfor(int i = 0; i < temp; i++)\r\n";readingStr += $"\t\t\t\t{name}[i] = " + GetFieldReadingStr(T)+";\r\n\r\n";}else if (type == "array"){string T = field.Attributes["T"].Value;readingStr += "\t\t\ttemp = 0;\r\n";readingStr += "\t\t\ttemp = " + GetFieldReadingStr("int") + ";\r\n";readingStr += "\t\t\tfor(int i = 0; i < temp; i++)\r\n";readingStr += $"\t\t\t\t{name}[i] = " + GetFieldReadingStr(T) + ";\r\n\r\n";}else if (type == "dic"){string Tkey = field.Attributes["Tkey"].Value;string Tvalue = field.Attributes["Tvalue"].Value;readingStr += "\t\t\ttemp = 0;\r\n";readingStr += "\t\t\ttemp = " + GetFieldReadingStr("int") + ";\r\n";readingStr += "\t\t\tfor(int i = 0; i < temp; i++)\r\n";readingStr += $"\t\t\t\t{name}.Add(" + GetFieldReadingStr(Tkey) +","+ GetFieldReadingStr(Tvalue) + ");\r\n\r\n";}else if (type == "enum"){string T = field.Attributes["T"].Value;readingStr += $"\t\t\t{name} = ({T})"+ GetFieldReadingStr("int") + ";\r\n";}else{readingStr += "\t\t\t"+$"{name} = "+ GetFieldReadingStr(type) + ";\r\n";}}return readingStr;}private string GetFieldReadingStr(string type){switch (type){case "long":return "ReadLong(bytes, ref index)";case "int":return "ReadInt(bytes, ref index)";case "enum":return "ReadInt(bytes, ref index)";case "float":return "ReadFloat(bytes, ref index)";case "byte":return "ReadByte(bytes, ref index)";case "bool":return "ReadBool(bytes, ref index)";case "short":return "ReadShort(bytes, ref index)";case "string":return "ReadString(bytes, ref index)";default:return $"ReadData<{type}>(bytes, ref index)";}}}

xml配置格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<messages><!--枚举配置规则--><enum name="E_PLAYER_TYPE" namespace ="GamePlayer"><field name = "MAIN">1</field><field name = "OTHER"/></enum><enum name="E_MONSTER_TYPE" namespace ="GameMonster"><field name = "NORMAL">1</field><field name = "BOSS"/></enum><!--数据结构类配置规则--><data name="PlayerData" namespace="GamePlayer"><field type="int" name="id"/><field type="float" name="atk"/><field type="long" name="lev"/><field type="array" T="int" name="arrays"/><field type="list" T="int" name="list"/><field type="list" T="string" name="listStr"/><field type="enum" T="E_PLAYER_TYPE" name="playerEnum"/><field type="dic" Tkey="int" Tvalue="string" name="dic"/></data><data name="MonsterData" namespace="GamePlayer"><field type="int" name="id"/><field type="float" name="atk"/><field type="long" name="lev"/><field type="array" T="int" name="arrays"/><field type="list" T="int" name="list"/><field type="list" T="string" name="listStr"/><field type="enum" T="E_PLAYER_TYPE" name="playerEnum"/><field type="dic" Tkey="int" Tvalue="string" name="dic"/></data><!--消息类配置规则--><message id="1001" name="PlayerMsg" namespace="GamePlayer"><field type="int" name="playerID"/><field type="PlayerData" name ="data"/></message><message id="1002" name="MonsterMsg" namespace="GamePlayer"><field type="int" name="MonsterID"/><field type="MonsterData" name ="data"/></message><message id="1" name="HeartMsg" namespace="GameSystem"/><message id="2" name="QuiteMsg" namespace="GameSystem"/>
</messages>

自定义协议工具生成为了方便后续消息类的添加,减少重复性的工作

点击[ProtocolTool]下的生成C#脚本

即可生成如下文件

列举【PlayerData】展示

using System;
using System.Text;
using System.Collections.Generic;namespace GamePlayer
{public class PlayerData : BaseData{public int id;public float atk;public long lev;public int[] arrays;public List<int> list;public List<string> listStr;public E_PLAYER_TYPE playerEnum;public Dictionary<int,string> dic;public override int GetBytesNum(){int num = 0;num += 4;num += 4;num += 8;num += 4;for (int i = 0; i < arrays.Length; i++)num += 4;num += 4;for (int i = 0; i < list.Count; i++)num += 4;num += 4;for (int i = 0; i < listStr.Count; i++)num += 4 + Encoding.UTF8.GetByteCount(listStr[i]);num += 4;num += 4;foreach (int key in dic.Keys){num += 4;num += 4 + Encoding.UTF8.GetByteCount(dic[key]);}return num;}public override byte[] Writing(){int index = 0;byte[] bytes = new byte[GetBytesNum()];WriteInt(bytes, id, ref index);WriteFloat(bytes, atk, ref index);WriteLong(bytes, lev, ref index);WriteInt(bytes, arrays.Length, ref index);for (int i = 0; i < arrays.Length; i++)WriteInt(bytes, arrays[i], ref index);WriteInt(bytes, list.Count, ref index);for (int i = 0; i < list.Count; i++)WriteInt(bytes, list[i], ref index);WriteInt(bytes, listStr.Count, ref index);for (int i = 0; i < listStr.Count; i++)WriteString(bytes, listStr[i], ref index);WriteInt(bytes, Convert.ToInt32(playerEnum), ref index);WriteInt(bytes, dic.Count, ref index);foreach(int key in dic.Keys){WriteInt(bytes, key, ref index);WriteString(bytes, dic[key], ref index);}return bytes;}public override int Reading(byte[] bytes, int beginIndex){int index = beginIndex;int temp = 0;id = ReadInt(bytes, ref index);atk = ReadFloat(bytes, ref index);lev = ReadLong(bytes, ref index);temp = 0;temp = ReadInt(bytes, ref index);for(int i = 0; i < temp; i++)arrays[i] = ReadInt(bytes, ref index);temp = 0;temp = ReadInt(bytes, ref index);for(int i = 0; i < temp; i++)list[i] = ReadInt(bytes, ref index);temp = 0;temp = ReadInt(bytes, ref index);for(int i = 0; i < temp; i++)listStr[i] = ReadString(bytes, ref index);playerEnum = (E_PLAYER_TYPE)ReadInt(bytes, ref index);temp = 0;temp = ReadInt(bytes, ref index);for(int i = 0; i < temp; i++)dic.Add(ReadInt(bytes, ref index),ReadString(bytes, ref index));return index -beginIndex;}}
}

自定义消息生成工具在附件中

http://www.dtcms.com/a/475041.html

相关文章:

  • 做宣传类网站需要什么资质浙江省建设执业注册中心网站
  • 怎么做视频解析的网站网站数据分析
  • 营销网站建站长沙营销型网站设计
  • 多输入,多输出来学英语
  • 矩阵的除法
  • 网站建设与优化推广方案内容WordPress安装插件要FTP
  • 合肥网站推广 公司哪家好手机论坛网站模板
  • 什么网站做唱歌主播网站建设 说明
  • 建设户外腰包网站旅游网站开发价格
  • CRYSTALS-Kyber在TLS 1.3中的实现挑战
  • 伴随矩阵的定义
  • PagedAttention详解
  • 网站搭建软件微信公众号对接网站如何做
  • 北京哪个公司做网站宁波网站设计制作
  • c2c模式的典型网站宜宾网站建设
  • 假网站网站怎么做网站关于我们什么意思
  • 个人如何网站备案临沂画册设计公司
  • 做网站提成软件公司都是干什么的
  • 后端八股之Redis
  • seo快速推广窍门大公开windows优化大师最新版本
  • 用帝国cms系统怎么做网站优化网站关键词的技巧
  • 建网站几个按钮哈尔滨seo优化培训
  • WebServer 02
  • 【完整源码+数据集+部署教程】腐蚀类型检测系统源码和数据集:改进yolo11-Faster
  • 【教学类-91-02】20251012笔记本电脑
  • 建站的公司浙江建设继续教育网站
  • 医院网站规划方案网站一定备案
  • 医疗器械网站建设策划书成都哪些公司做网站好
  • 【图像处理基石】遥感图像高度信息提取:Python实战全流程+常用库汇总
  • 大型网站要多少钱软文例文 经典软文范例