285 lines
8.2 KiB
C#
285 lines
8.2 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using XLua;
|
||
using System;
|
||
using System.IO;
|
||
|
||
namespace BF
|
||
{
|
||
public class LuaManager : ManagerBase
|
||
{
|
||
#region override
|
||
|
||
static LuaManager instance;
|
||
public static LuaManager Create()
|
||
{
|
||
BFLog.LogAssert(instance == null, "This method only allows BFMain to call once");
|
||
instance = new LuaManager();
|
||
return instance;
|
||
}
|
||
|
||
LuaManager() { }
|
||
|
||
public override void Init()
|
||
{
|
||
OnInit();
|
||
}
|
||
|
||
public override void Update()
|
||
{
|
||
OnUpdate();
|
||
}
|
||
|
||
public override void Destroy()
|
||
{
|
||
OnDestroy();
|
||
}
|
||
|
||
#endregion
|
||
|
||
internal LuaEnv luaEnv;
|
||
|
||
const float GCInterval = 1; // 1 second
|
||
float lastGCTime = 0;
|
||
|
||
Dictionary<string, byte[]> luaScriptDict = new Dictionary<string, byte[]>();
|
||
|
||
Action luaUpdate;
|
||
Action luaOnDestroy;
|
||
Action<string, string> luaOnLogMessageReceived;
|
||
Action<bool> luaOnApplicationFocus;
|
||
Action<bool> luaOnApplicationPause;
|
||
Action luaOnApplicationQuit;
|
||
Action gameInitSuccCallback;
|
||
|
||
AssetBundleConfigCollection Abcc { get { return BFMain.Instance.ResMgr.AbConfigCollection; } }
|
||
|
||
public bool DevExist = false;
|
||
|
||
void OnInit()
|
||
{
|
||
if (luaEnv == null)
|
||
{
|
||
#if UNITY_EDITOR
|
||
DevExist = Directory.Exists(Application.dataPath + "/Developer/lua");
|
||
#endif
|
||
Application.logMessageReceived += OnLogMessageReceived;
|
||
luaEnv = new LuaEnv();
|
||
luaEnv.AddBuildin("rapidjson", XLua.LuaDLL.Lua.LoadRapidJson);
|
||
luaEnv.AddBuildin("lpeg", XLua.LuaDLL.Lua.LoadLpeg);
|
||
luaEnv.AddBuildin("pb", XLua.LuaDLL.Lua.LoadLuaProfobuf);
|
||
}
|
||
}
|
||
|
||
void OnLogMessageReceived(string message, string stackTrace, LogType type)
|
||
{
|
||
if (type == LogType.Error || type == LogType.Exception)
|
||
{
|
||
luaOnLogMessageReceived?.Invoke(message, stackTrace);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化首包lua
|
||
/// </summary>
|
||
public void InitFirstLua(LuaEnv.CustomLoader loader)
|
||
{
|
||
BFLog.Log("加载首包lua first.lua");
|
||
luaEnv.ClearLoader();
|
||
luaEnv.AddLoader(loader);
|
||
|
||
luaEnv.DoString("require 'app/first/first'");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化main.lua 进入游戏
|
||
/// </summary>
|
||
public void InitGame(Action gameInitSuccCallback)
|
||
{
|
||
this.gameInitSuccCallback = gameInitSuccCallback;
|
||
|
||
luaEnv.ClearLoader();
|
||
luaEnv.AddLoader((ref string scriptPath) =>
|
||
{
|
||
var text = LoadGameLuaScriptText(scriptPath);
|
||
return text;
|
||
});
|
||
|
||
luaEnv.DoString("require 'main'");
|
||
#if HOTFIX_ENABLE
|
||
luaEnv.DoString("require 'app/hotfix/hotfixmain'");
|
||
#endif
|
||
}
|
||
|
||
byte[] LoadGameLuaScriptText(string scriptPath)
|
||
{
|
||
byte[] result = null;
|
||
if (!luaScriptDict.TryGetValue(scriptPath, out result))
|
||
{
|
||
#if !USE_AB && UNITY_EDITOR
|
||
result = LoadLuaDeveloperMode(scriptPath);
|
||
#else
|
||
result = LoadLuaStandardMode(scriptPath);
|
||
#endif
|
||
if (result != null)
|
||
{
|
||
luaScriptDict.Add(scriptPath, result);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
public byte[] LoadLuaDeveloperMode(string scriptPath)
|
||
{
|
||
byte[] result = null;
|
||
|
||
if (DevExist)
|
||
{
|
||
// 开发路径加载
|
||
var devLuaPath = Application.dataPath + "/Developer/lua/" + scriptPath + ".lua";
|
||
if (File.Exists(devLuaPath))
|
||
{
|
||
result = File.ReadAllBytes(devLuaPath);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("lua file is missing : " + devLuaPath);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 开发路径不存在,尝试bytes路径加载
|
||
var luaBytesPath = Application.dataPath + "/lua/" + scriptPath + ".lua.bytes";
|
||
if (File.Exists(luaBytesPath))
|
||
{
|
||
result = File.ReadAllBytes(luaBytesPath);
|
||
XLua.LuaDLL.Lua.decryptLua(ref result[0], result.Length);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("lua file is missing : " + luaBytesPath);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
byte[] LoadLuaStandardMode(string scriptPath)
|
||
{
|
||
byte[] result = LoadLuaAB(scriptPath);
|
||
|
||
if (result == null)
|
||
{
|
||
Debug.LogError("Lua assetBundle is missing : " + scriptPath + ".lua");
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
byte[] LoadLuaAB(string scriptPath)
|
||
{
|
||
var luaPath = "assets/lua/" + scriptPath + ".lua.bytes";
|
||
var abConfig = Abcc.GetConfigByAssetPath(luaPath);
|
||
|
||
string fullpath;
|
||
if (abConfig.location == 1)
|
||
{
|
||
fullpath = Path.Combine(Application.persistentDataPath, "update", abConfig.assetBundlePath);
|
||
}
|
||
else
|
||
{
|
||
fullpath = Path.Combine(Application.streamingAssetsPath, abConfig.assetBundlePath);
|
||
}
|
||
|
||
var ab = AssetBundle.LoadFromFile(fullpath);
|
||
var textAsset = ab.LoadAsset<TextAsset>(luaPath);
|
||
var bytes = textAsset.bytes.Clone() as byte[];
|
||
XLua.LuaDLL.Lua.decryptLua(ref bytes[0], bytes.Length);
|
||
ab.Unload(true);
|
||
return bytes;
|
||
}
|
||
|
||
public void GetGlobalLuaFunc()
|
||
{
|
||
luaEnv.Global.Get("luaUpdate", out luaUpdate);
|
||
luaEnv.Global.Get("luaOnDestroy", out luaOnDestroy);
|
||
luaEnv.Global.Get("luaOnLogMessageReceived", out luaOnLogMessageReceived);
|
||
luaEnv.Global.Get("luaOnApplicationFocus", out luaOnApplicationFocus);
|
||
luaEnv.Global.Get("luaOnApplicationPause", out luaOnApplicationPause);
|
||
luaEnv.Global.Get("luaOnApplicationQuit", out luaOnApplicationQuit);
|
||
}
|
||
|
||
public void OnGameInitSucc()
|
||
{
|
||
BFLog.Log("OnGameInitSucc");
|
||
gameInitSuccCallback?.Invoke();
|
||
gameInitSuccCallback = null;
|
||
BFMain.Instance.GameLaunchMgr.LaunchRequester.ClearLaunchSuccCallback();
|
||
}
|
||
|
||
public void ClearCache()
|
||
{
|
||
luaScriptDict.Clear();
|
||
}
|
||
|
||
public void LuaEnvTick()
|
||
{
|
||
luaEnv.Tick();
|
||
lastGCTime = Time.time;
|
||
}
|
||
|
||
public void LuaEnvFullGC(int count)
|
||
{
|
||
int defaultCheckCouunt = luaEnv.GetMaxCheckPerTick();
|
||
luaEnv.SetMaxCheckPerTick(count);
|
||
LuaEnvTick();
|
||
luaEnv.SetMaxCheckPerTick(defaultCheckCouunt);
|
||
}
|
||
|
||
void OnUpdate()
|
||
{
|
||
luaUpdate?.Invoke();
|
||
|
||
if (Time.time - lastGCTime > GCInterval)
|
||
{
|
||
luaEnv.Tick();
|
||
lastGCTime = Time.time;
|
||
}
|
||
}
|
||
|
||
public void OnApplicationFocus(bool hasFocus)
|
||
{
|
||
luaOnApplicationFocus?.Invoke(hasFocus);
|
||
}
|
||
|
||
public void OnApplicationPause(bool pauseStatus)
|
||
{
|
||
luaOnApplicationPause?.Invoke(pauseStatus);
|
||
}
|
||
|
||
public void OnApplicationQuit()
|
||
{
|
||
luaOnApplicationQuit?.Invoke();
|
||
}
|
||
|
||
void OnDestroy()
|
||
{
|
||
luaOnDestroy?.Invoke();
|
||
luaOnDestroy = null;
|
||
luaUpdate = null;
|
||
luaOnApplicationFocus = null;
|
||
luaOnApplicationPause = null;
|
||
luaOnApplicationQuit = null;
|
||
}
|
||
|
||
public void Clear()
|
||
{
|
||
luaUpdate = null;
|
||
luaOnDestroy = null;
|
||
luaOnLogMessageReceived = null;
|
||
luaOnApplicationFocus = null;
|
||
luaOnApplicationPause = null;
|
||
luaOnApplicationQuit = null;
|
||
gameInitSuccCallback = null;
|
||
}
|
||
}
|
||
} |