431 lines
10 KiB
Lua
431 lines
10 KiB
Lua
|
|
hg = {
|
|
loadedModules = {},
|
|
loadedModuleNameList = {}
|
|
}
|
|
|
|
local ModuleType = {
|
|
NoReturn = 1,
|
|
ReturnTable = 2,
|
|
ReturnUserData = 3,
|
|
}
|
|
|
|
function string.isEmpty(str)
|
|
return str == nil or str == ''
|
|
end
|
|
|
|
function string.upperFirst(str)
|
|
if not str or type(str) ~= "string" then
|
|
return str
|
|
end
|
|
return (str:gsub("^%l", string.upper))
|
|
end
|
|
|
|
function string.lowerFirst(str)
|
|
if not str or type(str) ~= "string" then
|
|
return str
|
|
end
|
|
return (str:gsub("^%u", string.lower))
|
|
end
|
|
|
|
function string.startWith(str, prefix)
|
|
if not str or not prefix then
|
|
return str
|
|
end
|
|
return string.find(str, prefix, 1, true) == 1
|
|
end
|
|
|
|
function string.endWith(str, suffix)
|
|
if not str or not suffix then
|
|
return str
|
|
end
|
|
return suffix == "" or string.sub(str, -#suffix) == suffix
|
|
end
|
|
|
|
|
|
function string.toSnakeCase(str)
|
|
if not str or type(str) ~= "string" then
|
|
return str
|
|
end
|
|
local newStr =
|
|
string.gsub(
|
|
str:sub(2),
|
|
"([%u%d]%l*)",
|
|
function(ss)
|
|
ss = "_" .. ss:lower()
|
|
return ss
|
|
end)
|
|
return str:sub(1, 1):lower() .. newStr
|
|
end
|
|
|
|
function string.split(str, delimiter)
|
|
if delimiter == "" then
|
|
return false
|
|
end
|
|
|
|
local pos, arr = 0, {}
|
|
|
|
for st, sp in function()
|
|
return string.find(str, delimiter, pos, true)
|
|
end do
|
|
table.insert(arr, string.sub(str, pos, st - 1))
|
|
pos = sp + 1
|
|
end
|
|
table.insert(arr, string.sub(str, pos))
|
|
return arr
|
|
end
|
|
|
|
function string.splitByLine(str)
|
|
local lines = {}
|
|
for line in string.gmatch(str, "[^\r\n]+") do
|
|
table.insert(lines, line)
|
|
end
|
|
return lines
|
|
end
|
|
|
|
function string.trim(str)
|
|
str = string.gsub(str, "^[ \t\n\r]+", "")
|
|
return string.gsub(str, "[ \t\n\r]+$", "")
|
|
end
|
|
|
|
function string.utf8len(s)
|
|
local len = 0
|
|
local i = 1
|
|
local byte = string.byte
|
|
while i <= #s do
|
|
local c = byte(s, i)
|
|
if c < 128 then
|
|
i = i + 1
|
|
len = len + 1
|
|
elseif c < 192 then
|
|
i = i + 1
|
|
elseif c < 224 then
|
|
i = i + 2
|
|
len = len + 1
|
|
elseif c < 240 then
|
|
i = i + 3
|
|
len = len + 1
|
|
elseif c < 248 then
|
|
i = i + 4
|
|
len = len + 1
|
|
elseif c < 252 then
|
|
i = i + 5
|
|
len = len + 1
|
|
elseif c < 254 then
|
|
i = i + 6
|
|
len = len + 1
|
|
end
|
|
end
|
|
return len
|
|
end
|
|
|
|
local function charSize(c)
|
|
if c < 128 then
|
|
return 1
|
|
elseif c < 192 then
|
|
return 1
|
|
elseif c < 224 then
|
|
return 2
|
|
elseif c < 240 then
|
|
return 3
|
|
elseif c < 248 then
|
|
return 4
|
|
elseif c < 252 then
|
|
return 5
|
|
elseif c < 254 then
|
|
return 6
|
|
end
|
|
logger.error("charSize error: " .. c)
|
|
return 0
|
|
end
|
|
|
|
function string.utf8sub(str, startChar, numChars)
|
|
local startIndex = 1
|
|
while startChar > 1 do
|
|
local char = string.byte(str, startIndex)
|
|
startIndex = startIndex + charSize(char)
|
|
startChar = startChar - 1
|
|
end
|
|
local currentIndex = startIndex
|
|
|
|
while numChars > 0 and currentIndex <= #str do
|
|
local char = string.byte(str, currentIndex)
|
|
currentIndex = currentIndex + charSize(char)
|
|
numChars = numChars - 1
|
|
end
|
|
return str:sub(startIndex, currentIndex - 1)
|
|
end
|
|
|
|
local RequireFailReason = {
|
|
NoFile = 1,
|
|
ReturnNotTable = 2,
|
|
Else = 3,
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function real_require_ex(moduleName, isReload, globalEnv)
|
|
globalEnv = globalEnv or _G
|
|
|
|
local module = hg.loadedModules[moduleName]
|
|
if not isReload and module then
|
|
return module.result or module.env
|
|
end
|
|
|
|
local ret, msg
|
|
if USING_VFS then
|
|
local content = LuaManagerInst:LoadLua(moduleName)
|
|
if content == nil then
|
|
return nil, RequireFailReason.NoFile, "No Lua File"
|
|
end
|
|
ret, msg = loadstring(content, "@" .. moduleName)
|
|
elseif not UNITY_EDITOR and USING_BUNDLE then
|
|
local content = LuaManagerInst:LoadLua(moduleName)
|
|
if content == nil then
|
|
return nil, RequireFailReason.NoFile, "No Lua File"
|
|
end
|
|
ret, msg = loadstring(content, "@" .. moduleName)
|
|
else
|
|
ret, msg = loadfile(LuaManagerInst:GetLuaFileRealPath(moduleName))
|
|
end
|
|
|
|
if ret == nil then
|
|
if string.find(msg, "No such file or directory") then
|
|
return nil, RequireFailReason.NoFile, msg
|
|
end
|
|
return nil, RequireFailReason.Else, msg
|
|
end
|
|
|
|
if not module then
|
|
|
|
local moduleEnv = setmetatable({}, {__index = globalEnv})
|
|
local retFunc = setfenv(ret, moduleEnv)
|
|
local succ, result = xpcall(retFunc, debug.traceback)
|
|
if not succ then
|
|
logger.critical(result)
|
|
return
|
|
end
|
|
|
|
module = {
|
|
name = moduleName,
|
|
env = moduleEnv
|
|
}
|
|
if result then
|
|
local typeStr = type(result)
|
|
if typeStr == "table" then
|
|
module.result = result
|
|
module.type = ModuleType.ReturnTable
|
|
elseif typeStr == "userdata" then
|
|
module.result = result
|
|
module.type = ModuleType.ReturnUserData
|
|
else
|
|
return nil, RequireFailReason.ReturnNotTable, "file can only return table or no return"
|
|
end
|
|
else
|
|
module.type = ModuleType.NoReturn
|
|
end
|
|
hg.loadedModules[moduleName] = module
|
|
hg.loadedModuleNameList[#hg.loadedModuleNameList + 1] = moduleName
|
|
else
|
|
|
|
local result = setfenv(ret, module.env)()
|
|
if module.type ~= ModuleType.NoReturn then
|
|
module.result = result
|
|
end
|
|
end
|
|
|
|
return module.result or module.env
|
|
end
|
|
|
|
local function parsePath(path)
|
|
if not path then
|
|
return
|
|
end
|
|
|
|
|
|
path = path:gsub("/+", "/")
|
|
|
|
|
|
while true do
|
|
local count
|
|
path, count = path:gsub("/[^/]-/%.%./", "/")
|
|
if count == 0 then
|
|
break
|
|
end
|
|
end
|
|
|
|
return path
|
|
end
|
|
|
|
local function getLocalModuleName(moduleName, isFromImport)
|
|
local info = debug.getinfo(isFromImport and 3 or 2)
|
|
local curPath = info.short_src
|
|
local pattern = "LuaScripts~/(.*/).*%.lua"
|
|
if USING_VFS then
|
|
pattern = "TextAsset/LuaScripts/(.*/).*%.lua"
|
|
elseif not UNITY_EDITOR and USING_BUNDLE then
|
|
pattern = "TextAsset/LuaScripts/(.*/).*%.lua"
|
|
end
|
|
local localModuleName
|
|
_, _, localModuleName = curPath:find(pattern)
|
|
if not localModuleName then
|
|
_, _, localModuleName = curPath:find("(.*/).*")
|
|
end
|
|
|
|
if localModuleName then
|
|
localModuleName = parsePath(localModuleName .. moduleName)
|
|
end
|
|
|
|
return localModuleName
|
|
end
|
|
|
|
function require_ex(moduleName, isReload, globalEnv, isFromImport)
|
|
moduleName = parsePath(moduleName)
|
|
local localModuleName
|
|
local result, reason, msg = real_require_ex(moduleName, isReload, globalEnv)
|
|
if result == nil and reason == RequireFailReason.NoFile then
|
|
logger.info("module not exist:", moduleName, msg, "\ntry require using localModuleName", localModuleName)
|
|
localModuleName = getLocalModuleName(moduleName, isFromImport)
|
|
if localModuleName then
|
|
result, reason, msg = real_require_ex(localModuleName, isReload, globalEnv)
|
|
end
|
|
end
|
|
|
|
if result == nil then
|
|
logger.error("require_ex fail", moduleName, isReload, reason, "\nerror message:", msg)
|
|
return
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
function require_check(moduleName)
|
|
moduleName = parsePath(moduleName)
|
|
if LuaManagerInst:IsLuaFileExist(moduleName) then
|
|
return true
|
|
end
|
|
|
|
local localModuleName = getLocalModuleName(moduleName)
|
|
return LuaManagerInst:IsLuaFileExist(localModuleName)
|
|
end
|
|
|
|
function addMetaIndex(t, index)
|
|
local mt = getmetatable(t)
|
|
if not mt then
|
|
setmetatable(t, {__index = index})
|
|
return
|
|
end
|
|
local oldIndex = mt.__index
|
|
local oldIsTable = type(oldIndex) == "table"
|
|
local newIsTable = type(index) == "table"
|
|
mt.__index = function(tt, k)
|
|
local value
|
|
if oldIndex ~= nil then
|
|
if oldIsTable then
|
|
value = oldIndex[k]
|
|
else
|
|
value = oldIndex(tt, k)
|
|
end
|
|
end
|
|
|
|
if value == nil then
|
|
if newIsTable then
|
|
value = index[k]
|
|
else
|
|
value = index(tt, k)
|
|
end
|
|
end
|
|
return value
|
|
end
|
|
end
|
|
|
|
function addMetaNewIndex(t, index)
|
|
local mt = getmetatable(t)
|
|
if not mt then
|
|
setmetatable(t, {__newindex = index})
|
|
return
|
|
end
|
|
local oldIndex = mt.__newindex
|
|
local newIsTable = type(index) == "table"
|
|
mt.__newindex = function(tt, k, value)
|
|
if newIsTable then
|
|
local action = index[k]
|
|
if action then
|
|
action(tt, k, value)
|
|
return
|
|
end
|
|
else
|
|
index(tt, k, value)
|
|
return
|
|
end
|
|
|
|
if oldIndex then
|
|
oldIndex(tt, k, value)
|
|
else
|
|
rawset(tt, k, value)
|
|
end
|
|
end
|
|
end
|
|
|
|
function import(moduleName)
|
|
local module = require_ex(moduleName, nil, nil, true)
|
|
local env = getfenv(2)
|
|
addMetaIndex(env, module)
|
|
end
|
|
|
|
function refreshScripts()
|
|
logger.info("refresh scripts .....")
|
|
hg.isReloading = true
|
|
HL.SetReloading(true)
|
|
for _, k in ipairs(hg.loadedModuleNameList) do
|
|
local succ, log = xpcall(require_ex, debug.traceback, k, true)
|
|
if not succ then
|
|
logger.critical(log)
|
|
end
|
|
end
|
|
HL.SetReloading(false)
|
|
hg.isReloading = false
|
|
end
|
|
|
|
function setmetatableindex(t, index)
|
|
local mt = getmetatable(t)
|
|
if not mt then
|
|
mt = {}
|
|
end
|
|
if not mt.__index then
|
|
mt.__index = index
|
|
setmetatable(t, mt)
|
|
elseif mt.__index ~= index then
|
|
setmetatableindex(mt, index)
|
|
end
|
|
end
|
|
|
|
function LuaIndex(index)
|
|
if not index then
|
|
return
|
|
end
|
|
return index + 1
|
|
end
|
|
|
|
function CSIndex(index)
|
|
if not index then
|
|
return
|
|
end
|
|
return index - 1
|
|
end
|
|
|
|
function isINF(value)
|
|
return value == math.huge or value == -math.huge
|
|
end
|
|
|
|
function isNAN(value)
|
|
return value ~= value
|
|
end
|
|
|
|
function isInvalidNumber(value)
|
|
return value == nil or isINF(value) or isNAN(value)
|
|
end
|