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 m_LuaXWABs = new Dictionary();//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(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(luaPath);// if (textAsset != null) { return textAsset.bytes; } } } foreach (var ab in m_LuaXWABs) { if (ab.Value != null && ab.Value != luaAB) { textAsset = m_LuaAB.LoadAsset(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)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("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("XWInit"); if (initFunc != null) { initFunc(); } //m_LuaEnv.DoString("MaPlayerPrefsin.Init()"); m_MainUpdate = m_LuaMain.Get("XWUpdate"); m_MainLateUpdate = m_LuaMain.Get("XWLateUpdate"); m_MainLogicUpdate = m_LuaMain.Get("XWFixedUpdate"); m_MainGUI = m_LuaMain.Get("XWGUI"); m_MainQuit = m_LuaMain.Get("XWQuit"); //Debug.Log($"'Main' Loaded {m_LuaEnv.Memroy}KB"); //m_bStart = true; //加载默认节点 string xid = XData.GetString("XWorldID"); //默认加载Lua开发模块 //Action AddModule = m_LuaMain.Get>("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 } }