forked from endernon/PGRData
164 lines
No EOL
5.4 KiB
Lua
164 lines
No EOL
5.4 KiB
Lua
-- 用于运行时热重载LUA逻辑,热键F3,在XDataCenter中初始化的相关Manager文件中涉及数据的改动需要重登或断线重连后生效(仅editor + debug模式下生效)
|
||
XHotReload = XHotReload or {}
|
||
|
||
local function updateFunc(newFunc, oldFunc)
|
||
assert("function" == type(newFunc))
|
||
assert("function" == type(oldFunc))
|
||
|
||
local newUpvalueDic = {}
|
||
for i = 1, math.huge do
|
||
local name, newValue = debug.getupvalue(newFunc, i)
|
||
if not name then break end
|
||
newUpvalueDic[name] = newValue
|
||
end
|
||
|
||
for i = 1, math.huge do
|
||
local name = debug.getupvalue(oldFunc, i)
|
||
if not name then break end
|
||
local newValue = newUpvalueDic[name]
|
||
if newValue then
|
||
debug.setupvalue(oldFunc, i, newValue)
|
||
end
|
||
end
|
||
end
|
||
|
||
local updateTable
|
||
function updateTable(newTable, oldTable)
|
||
if "table" ~= type(oldTable) then return end
|
||
if "table" ~= type(newTable) then return end
|
||
|
||
for key, newValue in pairs(newTable) do
|
||
local oldValue = oldTable[key]
|
||
local typeValue = type(newValue)
|
||
|
||
if typeValue == "table" then
|
||
updateTable(newValue, oldValue)
|
||
elseif typeValue == "function" then
|
||
updateFunc(newValue, oldValue)
|
||
end
|
||
oldTable[key] = newValue--此处未处理newTable中值数量少于oldTable的情况
|
||
end
|
||
|
||
local oldMeta = debug.getmetatable(oldTable)
|
||
local newMeta = debug.getmetatable(newTable)
|
||
if type(oldMeta) == "table" and type(newMeta) == "table" then
|
||
updateTable(newMeta, oldMeta)
|
||
end
|
||
end
|
||
|
||
local function TryRunInitConfig(fileName)
|
||
local _, endPos = string.find(fileName, "XConfig/")
|
||
if not endPos or endPos < 0 then return end
|
||
|
||
--local className = string.sub(fileName, endPos + 1)
|
||
-- 兼容加了一层文件夹
|
||
for i = 1, 99 do
|
||
local nextPos = string.find(fileName, "/", endPos + 1)
|
||
if nextPos and nextPos > 0 then
|
||
endPos = nextPos
|
||
end
|
||
end
|
||
local className = string.sub(fileName, endPos + 1)
|
||
|
||
local class = rawget(_G, className)
|
||
if not class then return end
|
||
|
||
if class.Init then class.Init() end
|
||
if class.__Configs then
|
||
class.__Configs = nil
|
||
end
|
||
end
|
||
|
||
local function TryReplaceMVCA(filePath, oldModule, newModule)
|
||
local _, endPos = string.find(filePath, "XModule/") --是新的业务开发框架
|
||
if not endPos or endPos < 0 then return end
|
||
local modulePath = string.sub(filePath, endPos + 1)
|
||
local moduleSplit = string.Split(modulePath, "/")
|
||
local moduleId = moduleSplit[1]
|
||
local fileName = moduleSplit[2]
|
||
--XLog.Error("fileName: ".. fileName)
|
||
if string.find(fileName, "Agency") then
|
||
if fileName == moduleId .. "Agency" then --这样可以过滤基类
|
||
XMVCA:_HotReloadAgency(moduleId)
|
||
end
|
||
elseif string.find(fileName, "Control") then
|
||
if fileName == moduleId .. "Control" then
|
||
XMVCA:_HotReloadControl(moduleId)
|
||
else
|
||
XMVCA:_HotReloadSubControl(moduleId, oldModule, newModule)
|
||
end
|
||
elseif string.find(fileName, "Model") then
|
||
XMVCA:_HotReloadModel(moduleId)
|
||
end
|
||
end
|
||
|
||
local function TryReplaceManager(filePath)
|
||
local _, endPos = string.find(filePath, "XManager/")
|
||
if not endPos or endPos < 0 then return end
|
||
local name = string.sub(filePath, endPos + 1)
|
||
|
||
local creatorName = string.format("%sCreator", name)
|
||
local managerVar = rawget(_G, creatorName) or rawget(_G, name)
|
||
if type(managerVar) == "function" then
|
||
local newManager = managerVar()
|
||
updateTable(newManager, XDataCenter[name])
|
||
elseif type(managerVar) == "table" and managerVar.Init then
|
||
managerVar.Init()
|
||
XLog.Debug(string.format("已重新运行%s的Init", name))
|
||
end
|
||
end
|
||
|
||
function XHotReload.Reload(fileName)
|
||
if not XMain.IsEditorDebug then return end
|
||
|
||
--local info = debug.getinfo(2)
|
||
if not package.loaded[fileName] then
|
||
XLog.Error("XHotReload.Reload reload file error: file never loaded, fileName is: ", fileName)
|
||
return
|
||
end
|
||
|
||
local oldModule = package.loaded[fileName]
|
||
package.loaded[fileName] = nil
|
||
|
||
local ok, err = pcall(require, fileName)
|
||
if not ok then
|
||
package.loaded[fileName] = oldModule
|
||
XLog.Error("XHotReload.Reload reload file error: ", err)
|
||
return
|
||
end
|
||
|
||
local newModule = package.loaded[fileName]
|
||
if "table" ~= type(newModule) then
|
||
TryRunInitConfig(fileName)--全局函数中只处理Config文件
|
||
end
|
||
updateTable(newModule, oldModule)
|
||
UpdateClassType(newModule, oldModule)
|
||
|
||
if "boolean" == type(newModule) then
|
||
TryReplaceManager(fileName) --改变XDataCenter所指向的Manager
|
||
end
|
||
TryReplaceMVCA(fileName, oldModule, newModule)
|
||
package.loaded[fileName] = oldModule
|
||
XLog.Debug("kkkttt XHotReload.Reload suc, fileName is: ", fileName)
|
||
end
|
||
|
||
-- 部分表在Manager里读取
|
||
function XHotReload.InitMgrTab()
|
||
if not XMain.IsDebug then return end
|
||
XReadOnlyTable.HotLoad = true
|
||
XConditionManager.Init()
|
||
XFightUiManager.Init()
|
||
XLoginManager.Init()
|
||
XPlayerManager.Init()
|
||
XResetManager.Init()
|
||
XRobotManager.Init()
|
||
XRoomSingleManager.Init()
|
||
|
||
XFunctionManager.Init()
|
||
XModelManager.Init()
|
||
XRewardManager.Init()
|
||
XReadOnlyTable.HotLoad = false
|
||
|
||
CS.XGame.ClientConfig:Init("Client/Config/ClientConfig.tab")
|
||
CS.XGame.Config:Init("Share/Config/Config.tab")
|
||
end |