Files
AIC-Project/Client/Assets/Script/xmain/Manager/LuaManager.cs
T
2026-07-10 10:24:29 +08:00

395 lines
13 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using UnityEngine;
using UnityEngine.Networking;
using XLua;
using static XLua.LuaEnv;
namespace XGame
{
public class LuaManager : MonoBehaviour
{
public static LuaEnv m_LuaEnv = null;// new LuaEnv();
public static LuaEnv.CustomLoader m_CustomLoader;
private const string LUA_SUFFIX = ".lua";
private const string BYTES_SUFFIX = ".bytes";
private const float INTERVAL = 1.0f;
//private bool m_bStart = false;
private float m_Timestamp = 0;
public static LuaManager m_Instance = null;
//系统lua
private AssetBundle m_LuaAB = null;
private LuaTable m_LuaMain = null;
private Action m_MainUpdate = null;
private Action m_MainLateUpdate = null;
private Action m_MainLogicUpdate = null;
private Action m_MainGUI = null;
private Action m_MainQuit = null;
//XWorld lua
private Dictionary<string, AssetBundle> m_LuaXWABs = new Dictionary<string, AssetBundle>();//xid, ab
private string m_curXID;
private void Awake()
{
m_Instance = this;
}
private void Start()
{
}
private IEnumerator LoadBaseLuaAB()
{
yield return XResLoader.GetFileDataOrigin("XWorld","bs.unity3d", (uwr) =>
{
if (uwr == null)
{
Debug.LogError($"Load AB Error: bs.unity3d");
}
else
{
byte[] decrypt = AESManager.Decrypt(uwr.downloadHandler.data);//bs.unity3d
m_LuaAB = AssetBundle.LoadFromMemory(decrypt);
Debug.Log("m_LuaAB Load OK!");
}
});
}
//Key : local或xid
public IEnumerator LoadAB(string Path, string Xid = null)
{
yield return XResLoader.coLoadFile(Path, (data) =>
{
if (data == null)
{
Debug.LogError($"Load AB Error: {Path}");
}
else
{
byte[] decrypt = AESManager.Decrypt(data);//bs.unity3d
AssetBundle ab = AssetBundle.LoadFromMemory(decrypt);
if (Xid != null)
m_LuaXWABs[Xid] = ab;
else
m_LuaXWABs[GlobalData.CurNode] = ab;
}
});
yield break;
}
public void ReleaseLua(string Xid)
{
if (Xid == null)
{//基础Lua,可能不需要即时释放
//释放lua
//。。。
//m_LuaAB.Unload(true);
}
else
{
if (m_LuaXWABs.ContainsKey(Xid))
{
AssetBundle ab = null;
if(m_LuaXWABs.TryGetValue(Xid, out ab))
{
ab.Unload(true);
m_LuaXWABs.Remove(Xid);
}
}
}
}
private IEnumerator LocalInit()
{
m_CustomLoader = (ref string path) =>
{//加载器 默认先从基础文件找,然后再去当前库找
string originalFixedPath = path.Replace('.', '/');
string fixedPath = originalFixedPath.ToLower();
//Debug.Log($"Base Loader : {fixedPath}");
byte[] content = null;
#if UNITY_EDITOR
//编辑器查找底层lua本地文件
if (File.Exists($"assets/lua/{fixedPath}.lua"))
{
content = System.IO.File.ReadAllBytes($"assets/lua/{fixedPath}.lua");
if (content != null)
{
return content;
}
}
#endif
TextAsset textAsset;
//然后查找底层ab
//根据文件路径在Assets/lua/路径里(或者luabytes里)加载lua
//先加载系统lua文件
string luaPath = $"assets/l/{fixedPath}.bytes";
if (m_LuaAB != null)
{
textAsset = m_LuaAB.LoadAsset<TextAsset>(luaPath);//
if (textAsset != null)
{
content = textAsset.bytes;
return content;
//Debug.LogError($"lua {path} not found!");
}
}
//Debug.LogError($"m_LuaAB {luaPath} not found!");
//非系统lua则寻找节点lua
//编辑器找本地
#if UNITY_EDITOR
//编辑器查找节点lua本地文件
//luaPath = $"assets/{GlobalData.CurNode}/script/{fixedPath}.lua";
luaPath = $"{Application.dataPath}/../../Lua/{fixedPath}.lua";
if (File.Exists(luaPath))
{
content = System.IO.File.ReadAllBytes(luaPath);
if (content != null)
{
return content;
}
}
luaPath = $"{Application.dataPath}/lua/{originalFixedPath}.lua";
if (File.Exists(luaPath))
{
content = System.IO.File.ReadAllBytes(luaPath);
if (content != null)
{
return content;
}
}
luaPath = $"{Application.dataPath}/lua/{fixedPath}.lua";
if (File.Exists(luaPath))
{
content = System.IO.File.ReadAllBytes(luaPath);
if (content != null)
{
return content;
}
}
luaPath = $"{Application.dataPath}/../../{originalFixedPath}.lua";
if (File.Exists(luaPath))
{
content = System.IO.File.ReadAllBytes(luaPath);
if (content != null)
{
return content;
}
}
luaPath = $"{Application.dataPath}/../../{fixedPath}.lua";
if (File.Exists(luaPath))
{
content = System.IO.File.ReadAllBytes(luaPath);
if (content != null)
{
return content;
}
}
#endif
luaPath = $"assets/l/{fixedPath}.bytes";
//Debug.Log($"lua {path} size:{textAsset.bytes.Length}!");
AssetBundle luaAB = null;
if (m_curXID != null && m_LuaXWABs.ContainsKey(m_curXID))
{
luaAB = m_LuaXWABs[m_curXID];
if (luaAB != null)
{
textAsset = m_LuaAB.LoadAsset<TextAsset>(luaPath);//
if (textAsset != null)
{
return textAsset.bytes;
}
}
}
foreach (var ab in m_LuaXWABs)
{
if (ab.Value != null && ab.Value != luaAB)
{
textAsset = m_LuaAB.LoadAsset<TextAsset>(luaPath);//
if (textAsset != null)
{
return textAsset.bytes;
}
}
}
return null;
};
yield return RestartLua();
yield break;
}
public IEnumerator RestartLua()
{
if (m_LuaEnv != null)
{
m_LuaEnv.Dispose();
m_LuaEnv = null;
if (m_LuaAB != null)
{
m_LuaAB.Unload(true);
m_LuaAB = null;
}
m_LuaMain = null;
m_MainUpdate = null;
m_MainLateUpdate = null;
m_MainLogicUpdate = null;
m_MainGUI = null;
m_MainQuit = null;
GC.Collect();
}
//修改默认加载位置xid或local
m_LuaEnv = new LuaEnv();//*/
if (m_LuaAB == null)
{
Debug.Log("Init m_LuaAB");
yield return LoadBaseLuaAB();
}
m_LuaEnv.AddLoader(m_CustomLoader);
//默认函数
m_LuaEnv.Global.Set("XWorldGetTime", (System.Func<double>)Utility.XWorldGetTime);
Debug.Log($"LuaManager Init 'XWMain' {m_LuaEnv.Memroy}KB");
//无需使用lua
yield break;
//默认lua入口文件
m_LuaEnv.DoString("require'XWBaseLua.XWMain'");
Debug.Log("require'XWBaseLua.XWMain'");
m_LuaMain = m_LuaEnv.Global.Get<LuaTable>("XWMain");
if (m_LuaMain == null)
{
Debug.LogError("Error: Lua 'Main' Not Found !");
yield break;
}
//m_LuaEnv.DoString("_G.Main=nil");//全局的置空
Action initFunc = m_LuaMain.Get<Action>("XWInit");
if (initFunc != null)
{
initFunc();
}
//m_LuaEnv.DoString("MaPlayerPrefsin.Init()");
m_MainUpdate = m_LuaMain.Get<Action>("XWUpdate");
m_MainLateUpdate = m_LuaMain.Get<Action>("XWLateUpdate");
m_MainLogicUpdate = m_LuaMain.Get<Action>("XWFixedUpdate");
m_MainGUI = m_LuaMain.Get<Action>("XWGUI");
m_MainQuit = m_LuaMain.Get<Action>("XWQuit");
//Debug.Log($"'Main' Loaded {m_LuaEnv.Memroy}KB");
//m_bStart = true;
//加载默认节点
string xid = XData.GetString("XWorldID");
//默认加载Lua开发模块
//Action<string> AddModule = m_LuaMain.Get<Action<string>>("AddModule");
//AddModule("client/client");
#if UNITY_EDITOR
#endif
yield break;
}
public static IEnumerator Init()
{
yield return m_Instance.LocalInit();
}
private void Update()
{
float now = Time.time;
if (m_MainUpdate != null)
{
try
{
m_MainUpdate();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
if (!(now > m_Timestamp + INTERVAL))
{
return;
}
m_Timestamp = now;
if(m_LuaEnv != null)
m_LuaEnv.Tick();
}
private void LateUpdate()
{
if (m_MainLateUpdate != null)
{
try
{
m_MainLateUpdate();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
private void FixedUpdate()
{ //
if (m_MainLogicUpdate != null)
{
m_MainLogicUpdate();
}
}
private void OnGUI()
{
if (m_MainGUI != null)
{
try
{
m_MainGUI();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
public void DoString(string sLuaString)
{
m_LuaEnv.DoString(sLuaString);
}
private void OnApplicationQuit()
{
if(m_MainQuit != null)
m_MainQuit();
}
#if UNITY_EDITOR
//热更新lua
private void OnLuaFileChange(string filePath)
{
if (string.IsNullOrEmpty(filePath) || !filePath.EndsWith(LUA_SUFFIX, StringComparison.OrdinalIgnoreCase))
{
return;
}
//重载文件
//filePath = filePath.Replace('\\', '/');
//int startIndex = filePath.IndexOf(LuaEditorBaseUrl) + 7;
//filePath = filePath.Substring(startIndex, filePath.Length - startIndex - LUA_SUFFIX.Length);
//Invoke("ToolManager.ReloadLuaFile", filePath);
}
#endif
}
}