Slua的服务器端导出

 我还记得第一天来到乐趣,我的上司也就是主程就分配了我一个任务,时间给我安排的是2天,由于他不是很了解我的水平,估计是想用这个试试我吧! 不过我也不是什么水货,当时我预估了一下感觉这个东西最多也就半天可以搞定吧! 于是我就开始撸代码了………….

   他给我的任务是要把服务器端的C#代码导出slua代码,目的是为了在服务器端使用lua代码.

于是我就开始看slua的源码,由于我之前没有接触过slua,只看过ulua的代码,而且没有使用过slua进行热更新过.但是我发现看了以后slua的导出和ulua的代码导出基本上是差不多的.原理也差不多只是风格可能有所不同,听网上说是ulua的性能比slua要好,不知道为什么公司要用slua.

  既然他要我导出,那我肯定要从unity3D里面的slua导出里面开始看,其实slua的代码导出主要是在 "LuaCodeGen.cs" 这个C#文件.也就是说 基本把这文件上得代码或者类看懂就行了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public  class  LuaCodeGen : MonoBehaviour     //这个类是继承自MonoBehaviour
     {
         static  public  string  GenPath = SLuaSetting.Instance.UnityEngineGeneratePath;
         public  delegate  void  ExportGenericDelegate(Type t,  string  ns);
         
         static  bool  autoRefresh =  true ;
 
         static  bool  IsCompiling {
             get  {
                 if  (EditorApplication.isCompiling) {
                     Debug.Log( "Unity Editor is compiling, please wait." );
                 }
                 return  EditorApplication.isCompiling;
             }
         }
          
         [InitializeOnLoad]
         public  class  Startup
         {
             static  bool  isPlaying= false ;
             static  Startup()
             {
                 EditorApplication.update += Update;
                 // use this delegation to ensure dispose luavm at last
                 EditorApplication.playmodeStateChanged+=()=>{
                     
                     if (isPlaying== true  && EditorApplication.isPlaying== false ) {
                         if (LuaState.main!= null ) LuaState.main.Dispose();
                     }
 
                     isPlaying=EditorApplication.isPlaying;
                 };
            
 
 
         static  void  Update(){
                EditorApplication.update -= Update;
                Lua3rdMeta.Instance.ReBuildTypes();
 
                 // Remind user to generate lua interface code
                var  remindGenerate = !EditorPrefs.HasKey( "SLUA_REMIND_GENERTE_LUA_INTERFACE" ) ||
                  EditorPrefs.GetBool( "SLUA_REMIND_GENERTE_LUA_INTERFACE" );
                 bool  ok = System.IO.Directory.Exists(GenPath+ "Unity" );
                 if  (!ok && remindGenerate)
                 {
                  if  (EditorUtility.DisplayDialog( "Slua" , "Not found lua  interface  for 
                  Unity, generate it now? ", " Generate ", " No"))
                    {
                      GenerateAll();
                    }
                     else
                     {
                       if (!EditorUtility.DisplayDialog( "Slua" , "Remind you next time 
                       when no lua  interface  found  for  Unity? ", " OK",
                             "Don't remind me next time!" ))
                        {
                           EditorPrefs.SetBool( "SLUA_REMIND_GENERTE_LUA_INTERFACE" false );
                        }
                         else
                         {
                             
                           EditorPrefs.SetBool( "SLUA_REMIND_GENERTE_LUA_INTERFACE" true );
                         }
                         
                     }
                 }
             }
 
         }
     
         [MenuItem( "SLua/All/Make" )]
         static  public  void  GenerateAll()   //这里是 导出的入口函数
         {
                         autoRefresh =  false ;
                         Generate();
             GenerateUI();
             Custom();
             Generate3rdDll();
                         autoRefresh =  true ;
                         AssetDatabase.Refresh();
         }

   可能看到 在U3D中的导出SLUA的菜单按钮中是执行了 GenerateAll() 这个函数,这个函数的意思是导出全部的U3D的SLUA代码

这个函数里面有执行了 

1
2
3
4
5
6
  Generate();
  GenerateUI();
  Custom();
  Generate3rdDll();
  autoRefresh =  true ;
  AssetDatabase.Refresh();

这个几个函数,其中Generate();这个函数是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  static  public  void  Generate()
         {
             if  (IsCompiling) {
                 return ;
             }
 
             Assembly assembly = Assembly.Load( "UnityEngine" );
             Type[] types = assembly.GetExportedTypes();
             
             List< string > uselist;
             List< string > noUseList;
             
             CustomExport.OnGetNoUseList( out  noUseList);
             CustomExport.OnGetUseList( out  uselist);
 
             // Get use and nouse list from custom export.
             object [] aCustomExport =  new  object [1];
             InvokeEditorMethod<ICustomExportPost>( "OnGetUseList" ref  aCustomExport);
             if  ( null  != aCustomExport[0])
             {
                 if  ( null  != uselist)
                 {
                     uselist.AddRange((List< string >)aCustomExport[0]);
                 }
                 else
                 {
                     uselist = (List< string >)aCustomExport[0];
                 }
             }
 
             aCustomExport[0] =  null ;
             InvokeEditorMethod<ICustomExportPost>( "OnGetNoUseList" ref  aCustomExport);
             if  ( null  != aCustomExport[0])
             {
                 if  (( null  != noUseList))
                 {
                     noUseList.AddRange((List< string >)aCustomExport[0]);
                 }
                 else
                 {
                     noUseList = (List< string >)aCustomExport[0];
                 }
             }
 
             List<Type> exports =  new  List<Type>();
             string  path = GenPath +  "Unity/" ;
             foreach  (Type t  in  types)
             {
                 if  (filterType(t, noUseList, uselist) && Generate(t, path))
                     exports.Add(t);
             }
             
             GenerateBind(exports,  "BindUnity" , 0, path);
             if (autoRefresh)
                 AssetDatabase.Refresh();
             Debug.Log( "Generate engine interface finished" );
         }

 可以看到这个函数有这么一句, 也就是说他是利用反射把UnityEngine.dll 里面的函数全部导出来了.

1
Assembly assembly = Assembly.Load( "UnityEngine" );

1
GenerateUI(); //则是把unity里面的UI函数接口导出来了.
1
2
Custom();  //则是把客户端用户标记的C#代码导出来
Generate3rdDll();  //则是把3rdDll导出来;

而 Generate(),GenerateUI();Generate3rdDll(); 这几个函数在服务器端是不需要的,因为服务器端是没有unity3D函数的.

所以只要修改Custom();函数就可以了,然后在需要导出的类前面加上导出的标记.就可以导出服务器端的代码.

具体修改如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  static  public  void  Custom()
         {
             List<Type> exports =  new  List<Type>();
             string  path = GenPath +  "/Server/Server/LuaExport/" ; //修改导出路径 这个可以自行定义
             if  (!Directory.Exists(path))
             {
                 Directory.CreateDirectory(path);
             }
             ExportGenericDelegate fun = (Type t,  string  ns) =>
             {
                 if  (Generate(t, ns, path))
                 {
                     exports.Add(t);
                     Debug.LogFormat( "{0} exported..." , t.FullName);
                 }
             };
 
             Assembly assembly;
             Type[] types;
             // export self-dll
             assembly = Assembly.GetExecutingAssembly(); //这句是最重要的,它的意思是获取当前正在运行的程序的函数然后导出来,也就是导出自身DLL代码
             types = assembly.GetExportedTypes();
             foreach  (Type t  in  types)
             {
                 if  (t.IsDefined( typeof (CustomLuaClassAttribute),  false ))
                 {
                     fun(t,  null );
                 }
             }
 
             CustomExport.OnAddCustomClass(fun); //添加导出类
 
             GenerateBind(exports,  "BindCustom" , 3, path); //绑定
         }

最后把有关于U3D的代码去掉和多余的代码去掉就可以了.在需要导出的类上面添加 [SLua.CustomLuaClass] 特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using  System.Collections;
using  UnityEngine;
[SLua.CustomLuaClass]  //添加标记 代表这个类会被导出
public  partial  class  DieController : UnitBaseComponent
{
     public  void  DoDie( int  attackerIdx,  int  attackType, Damage.CreatureHit hit)
     {
         DoDieImpl(attackerIdx, attackType, hit);
 
         var  writer =  new  CombatProtocolWriter(sceneObject_, CombatProtocolEnum.S2C_SyncDie);
         writer.Write(attackerIdx);
         writer.Write(attackType);
 
         #region 附带被击效果
         if  (hit !=  null )
         {
             writer.Write( true );
             writer.Write(hit.attackPosition);
             writer.Write(hit.creatureHitID);
             writer.Write(hit.attackerObjID);
         }
         else
         {
             writer.Write( false );
         }
         #endregion
 
         room_.Broadcast(writer);
     }

然后再服务器端的Main函数里 添加一个导出命令参数就可以导出相应的类了

1
2
3
4
5
6
7
8
    
         if (args.Length >= 1 &&  "lua_export"  == args[0])
         {
             Debug.Log( "Running in lua export mode..." );
             LuaCodeGen.GenerateAll();  //调用导出函数
             AddNewLuaExport();  //给VS项目添加新生成的Slua导出文件
             return ;
         }

如添加一个 lua_export 命令, 在VS里面设置一下

QQ截图20161028232257.png

启动程序后就可以导出了 

   另外还有一个小工具是,当你新生成的SLUA代码是不会自动添加到VS 的C#项目里面的还需要修改项目里的配置文件才会自动添加进去 所以我有做了一个小工具可以把新生成的 C#文件添加到项目中.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
private  static  void  AddNewLuaExport() //也就是生成后需要执行的函数
     {
         List< string > fileList =  new  List< string >();
         DirectoryInfo folder =  new  DirectoryInfo( "../../Server/Server/LuaExport" );
         foreach (FileInfo NextFile  in  folder.GetFiles())
         {
             fileList.Add( "Server\\LuaExport\\"  + NextFile.Name);
         }
         ModifyCsproj( "../../Server/Server.csproj" , fileList);
     }
     
private  static  void  ModifyCsproj( string  xmlFilePath, List< string > csFileList)
     {
         XmlDocument xmlDoc =  new  XmlDocument();
         xmlDoc.Load(xmlFilePath);
         XmlNodeList root_childlist = xmlDoc.ChildNodes;
         XmlNode root_Project =  null ;
 
         foreach (XmlNode xn  in  root_childlist)
         {
             if (xn.Name ==  "Project" )
             {
                 root_Project = xn;
                 break ;
             }
         }
         XmlNodeList childlist_Project = root_Project.ChildNodes;
         XmlNodeList childlist_Item =  null ;
         XmlNode node_Compile =  null ;
         List<XmlNode> nodes =  new  List<XmlNode>();
         foreach (XmlNode xn  in  childlist_Project)
         {
             if (xn.Name ==  "ItemGroup" )
             {
                 if (xn.FirstChild.Name ==  "Compile" )
                 {
                     node_Compile = xn;
                     childlist_Item = node_Compile.ChildNodes;
                     break ;
                 }
             }
         }
         foreach (XmlElement x  in  childlist_Item)
         {
             if (x.GetAttribute( "Include" ).Contains( "LuaExport" ))
             {
                 nodes.Add(x);
             }
         }
         for ( int  i = 0; i < nodes.Count; i++)
         {
             node_Compile.RemoveChild(nodes[i]);
         }
         foreach ( string  fileName  in  csFileList)
         {
          XmlElement xe_Compile = xmlDoc.CreateElement( "Compile"
          
          xmlDoc.DocumentElement.NamespaceURI);
          
          xe_Compile.SetAttribute( "Include" , fileName);
          node_Compile.AppendChild(xe_Compile);
         }
         xmlDoc.Save(xmlFilePath);
     }

最后的福利就是把完整的导出代码也共享出来 哈哈 

百度网盘:http://pan.baidu.com/s/1hrD58XY

发布了22 篇原创文章 · 获赞 14 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/a13677972680/article/details/52994046