748 lines
24 KiB
Lua
748 lines
24 KiB
Lua
local breakSocketHandle, debugXpCall = require("LuaDebugjit")("localhost", 7003)
|
||
local timer = Timer.New(function()
|
||
breakSocketHandle()
|
||
end, 1, -1, false)
|
||
timer:Start();
|
||
|
||
require "Core.init"
|
||
json = require 'cjson'
|
||
require 'FairyGUI'
|
||
require 'Game.ControllerManager'
|
||
require 'Game.ViewManager'
|
||
require 'Game.DataManager'
|
||
require "Game.ExtendManager"
|
||
require "Game.ExtendHotupdate"
|
||
require "TableData"
|
||
|
||
MsgParser = require("MsgParser")
|
||
|
||
Utils = Game.Utils
|
||
PlayerPrefs = UnityEngine.PlayerPrefs
|
||
RuntimePlatform = UnityEngine.RuntimePlatform
|
||
Application = UnityEngine.Application
|
||
Screen = UnityEngine.Screen
|
||
ResourcesManager = taurus.unity.ResourcesManager
|
||
-- require 'tolua.reflection'
|
||
-- tolua.loadassembly('Assembly-CSharp')
|
||
-- local BindingFlags = require 'System.Reflection.BindingFlags'
|
||
|
||
|
||
|
||
local _game_info
|
||
local panel = nil
|
||
|
||
|
||
oldGameVersion = 2 --1 原始 2 老游戏新加功能
|
||
|
||
--主入口函数。从这里开始lua逻辑
|
||
function Main()
|
||
if true then
|
||
local suc = pcall(function()
|
||
local path = Application.streamingAssetsPath .. "/../../.."
|
||
package.cpath = package.cpath .. ";" .. path .. "/?.dll"
|
||
local dbg = require("emmy_core")
|
||
dbg.tcpConnect('localhost', 9966)
|
||
end)
|
||
if suc then
|
||
print("=============================调试连接成功!===========================")
|
||
end
|
||
end
|
||
|
||
-- PlayerPrefs.DeleteKey('session_id')
|
||
Application.targetFrameRate = 60
|
||
FairyGUI.UIConfig.buttonSound = FairyGUI.NAudioClip(ResourcesManager.LoadObject("base/common/sound/click.mp3",
|
||
typeof(UnityEngine.AudioClip)))
|
||
FairyGUI.UIConfig.defaultFont = "FZDaBiaoSong-B06S"
|
||
FairyGUI.FontManager.RegisterFont(FairyGUI.DynamicFont.New("SIYUAN", "base/static/fonts/SIYUAN.TTF"), null)
|
||
FairyGUI.FontManager.RegisterFont(
|
||
FairyGUI.DynamicFont.New("AlimamaFangYuanTiVF-Thin", "base/static/fonts/AlimamaFangYuanTiVF-Thin.ttf"), null)
|
||
FairyGUI.FontManager.RegisterFont(
|
||
FairyGUI.DynamicFont.New("AlimamaFangYuanTi-MediumRound", "base/static/fonts/AlimamaFangYuanTi-MediumRound.TTF"),
|
||
null)
|
||
FairyGUI.FontManager.RegisterFont(
|
||
FairyGUI.DynamicFont.New("AlimamaFangYuanTi-SemiBoldRound", "base/static/fonts/AlimamaFangYuanTi-SemiBoldRound.TTF"),
|
||
null)
|
||
|
||
FairyGUI.FontManager.RegisterFont(
|
||
FairyGUI.DynamicFont.New("AlimamaFangYuanTi-BoldRound-700", "base/static/fonts/AlimamaFangYuanTi-BoldRound-700.TTF"),
|
||
null)
|
||
_game_info = json.decode(GameApplication.Instance.GameInfo)
|
||
--_game_info["login_url"]="http://8.134.59.224:8101/"
|
||
--pt(_game_info)
|
||
debug_print = false --GetGameInfo("debug_print")
|
||
if Application.platform == RuntimePlatform.WindowsEditor then
|
||
debug_print = true
|
||
end
|
||
debug_print = true
|
||
local NetManager = taurus.client.NetManager
|
||
NetManager.debug_print = debug_print
|
||
-- 网络延时8秒
|
||
NetManager.TIMEOUT_TIME = 10
|
||
|
||
UIPackage.AddPackage("base/common/ui/Common")
|
||
panel = UIPackage.CreateObjectFromURL("ui://Common/UIPanel")
|
||
GRoot.inst:AddChildAt(panel, 0)
|
||
panel:MakeFullScreen()
|
||
panel:AddRelation(GRoot.inst, RelationType.Size)
|
||
--web网络API版本号
|
||
NetManager.VERSION = GetGameInfo("net_version")
|
||
|
||
TimerManager.New()
|
||
-- test:DynamicInvoke("222")
|
||
--ExtendManager.Init()
|
||
ControllerManager.Init()
|
||
ViewManager.Init()
|
||
|
||
ControllerManager.ChangeController(LoginController)
|
||
ViewManager.ChangeView(ViewManager.View_Login)
|
||
DataManager.AppVersion = GetGameInfo("app_version")
|
||
|
||
get_gps()
|
||
local timer = 0
|
||
local DSTweenManager = ds.tween.DSTweenManager
|
||
UpdateBeat:Add(function()
|
||
local deltaTime = Time.deltaTime
|
||
DSTweenManager.Update(deltaTime)
|
||
timer = timer + deltaTime
|
||
if timer >= 60 then
|
||
timer = 0
|
||
local ctr = ControllerManager.GetCurrenController()
|
||
if DataManager.CurrenRoom and ctr.baseType == GameController then
|
||
ctr:GetGPS()
|
||
else
|
||
get_gps()
|
||
end
|
||
end
|
||
end)
|
||
end
|
||
|
||
function GetGameInfo(key)
|
||
return _game_info[key]
|
||
end
|
||
|
||
function GetPlatform()
|
||
return ResourcesManager.OS_Dir
|
||
end
|
||
|
||
function GetGameInfoPlatform(key)
|
||
local p_key = GetPlatform()
|
||
local _platfrom = _game_info[p_key]
|
||
return _platfrom[key]
|
||
end
|
||
|
||
function BlurView(view, enabled)
|
||
if enabled then
|
||
local bf = FairyGUI.BlurFilter()
|
||
bf.blurSize = 0.05
|
||
view.filter = bf
|
||
else
|
||
view.filter = null
|
||
end
|
||
end
|
||
|
||
function ShareScreenShotWithOption(callback, index)
|
||
--分享目标选择,包括分享截图到 微信/支付宝
|
||
local wx_win = BaseWindow.new("ui://Common/Win_WXShareWin", nil)
|
||
wx_win._close_destroy = true
|
||
wx_win._view:GetController("c1").selectedIndex = index or 3
|
||
local cb = function()
|
||
if callback then callback() end
|
||
end
|
||
wx_win._view:GetChild("btn_wx_session").onClick:Add(function()
|
||
wx_win:Destroy()
|
||
ShareScreenShot(1, callback)
|
||
end)
|
||
wx_win:Show()
|
||
end
|
||
|
||
function ShareScreenShot(n, callback)
|
||
local json_data = {}
|
||
json_data["title"] = "游戏"
|
||
local mediaObject = {}
|
||
mediaObject["path"] = Application.persistentDataPath
|
||
mediaObject["filename"] = "screenshot"
|
||
mediaObject["type"] = 1
|
||
json_data["mediaObject"] = mediaObject
|
||
json_data["description"] = "一款现实中朋友约局休闲娱乐的场所!速度约朋友一起来玩吧!"
|
||
json_data["scene"] = 0
|
||
local json_str = json.encode(json_data)
|
||
TakeScreenShot.Take(function()
|
||
-- 1微信 2支付宝
|
||
GameApplication.Instance:ShareLink(n or 1, json_str, nil)
|
||
if callback then
|
||
callback()
|
||
end
|
||
end)
|
||
end
|
||
|
||
function shareQRCodePicture(url, secene)
|
||
--print(debug.traceback())
|
||
print(url)
|
||
print(secene)
|
||
local json_data = {}
|
||
json_data["title"] = "联赛"
|
||
local mediaObject = {}
|
||
local filename = "qrcode" .. DataManager.SelfUser.account_id
|
||
print(Application.persistentDataPath)
|
||
mediaObject["path"] = Application.persistentDataPath
|
||
mediaObject["filename"] = filename
|
||
mediaObject["type"] = 1
|
||
json_data["mediaObject"] = mediaObject
|
||
json_data["description"] = "一款现实中朋友约局休闲娱乐的场所!速度约朋友一起来玩吧!"
|
||
json_data["scene"] = secene
|
||
print("json_data==================")
|
||
local json_str = json.encode(json_data)
|
||
pt(json_str)
|
||
local tex2 = QRCodePicture.GenerateQRcode(url, 250, 250)
|
||
local tex1 = ResourcesManager.LoadObject("base/lobby/bg/bg.png", typeof(UnityEngine.Texture2D))
|
||
filename = filename .. ".jpg"
|
||
print("text2==========")
|
||
print(tex2)
|
||
print("text1==========")
|
||
print(tex1)
|
||
print("filename==========")
|
||
print(filename)
|
||
QRCodePicture.CombanitePicture(tex1, tex2, 393, 1334 - 802 - 250, filename)
|
||
|
||
GameApplication.Instance:ShareLink(1, json_str, nil)
|
||
end
|
||
|
||
function ShareChatRoom(room_id, share_time, round, game_name, group_id, player_list, _root_view, play_name)
|
||
|
||
end
|
||
|
||
function UISetController(root, controller_name, gear_display, selectedIndex)
|
||
local ctr = root:GetController(controller_name)
|
||
local gear = gear_display:GetGear(0)
|
||
|
||
gear.controller = ctr
|
||
gear.pages = { ctr:GetPageId(selectedIndex) }
|
||
gear_display:HandleControllerChanged(ctr)
|
||
end
|
||
|
||
local bg_url = nil
|
||
function LoadGameBg(url, main_view)
|
||
local win_mode = main_view:GetChild("win_mode")
|
||
win_mode:RemoveChildren(0, -1, true)
|
||
local tex_bg = ResourcesManager.LoadObjectByGroup(url .. ".png", typeof(UnityEngine.Texture), url)
|
||
local bg = GImage()
|
||
bg.texture = FairyGUI.NTexture(tex_bg)
|
||
bg.width = win_mode.width
|
||
bg.height = win_mode.height
|
||
bg:AddRelation(win_mode, RelationType.Size)
|
||
win_mode:AddChild(bg)
|
||
|
||
-- 卸载资源
|
||
if url ~= bg_url and bg_url then
|
||
ResourcesManager.UnLoadGroup(bg_url)
|
||
end
|
||
bg_url = url
|
||
end
|
||
|
||
function AddPanel(child)
|
||
child:MakeFullScreen()
|
||
child:AddRelation(GRoot.inst, RelationType.Size)
|
||
panel:AddChild(child)
|
||
end
|
||
|
||
function AddPanelAt(child, index)
|
||
child:MakeFullScreen()
|
||
child:AddRelation(GRoot.inst, RelationType.Size)
|
||
panel:AddChildAt(child, index)
|
||
end
|
||
|
||
function AddPanelCenter(child)
|
||
panel:AddChild(child)
|
||
child:Center(true)
|
||
end
|
||
|
||
--重启游戏
|
||
function RestartGame()
|
||
DSTweenManager.ClearTween()
|
||
panel:Dispose()
|
||
coroutine.stopAll()
|
||
BaseWindow.DestroyAll()
|
||
GameApplication.Instance:RestartGame()
|
||
end
|
||
|
||
--场景切换通知
|
||
function OnLevelWasLoaded(level)
|
||
Time.timeSinceLevelLoad = 0
|
||
end
|
||
|
||
--程序切到后台
|
||
function OnApplicationPause()
|
||
-- ViewUtil.CloseModalWait()
|
||
ViewManager.OnApplicationPause()
|
||
end
|
||
|
||
--程序从后台切回
|
||
function OnApplicationActive()
|
||
ViewManager.OnApplicationActive()
|
||
end
|
||
|
||
function pt(...)
|
||
if debug_print then
|
||
local arg = { ... }
|
||
local has = false
|
||
for _, v in pairs(arg) do
|
||
if v and type(v) == "table" then
|
||
has = true
|
||
break
|
||
end
|
||
end
|
||
if not has then
|
||
print(...)
|
||
end
|
||
|
||
local content = ""
|
||
for _, v in pairs(arg) do
|
||
if v == "table" then
|
||
content = content .. tostring(v) .. "\n"
|
||
else
|
||
content = content .. "==>[T]:" .. LuaPrint(v, limit), debug.traceback() .. "\n"
|
||
end
|
||
print(content)
|
||
end
|
||
end
|
||
end
|
||
|
||
function LuaPrint(lua_table, limit, indent, step)
|
||
step = step or 0
|
||
indent = indent or 0
|
||
local content = ""
|
||
if limit ~= nil then
|
||
if step > limit then
|
||
return "..."
|
||
end
|
||
end
|
||
if step > 10 then
|
||
return content .. "..."
|
||
end
|
||
if lua_table == nil then
|
||
return "nil"
|
||
end
|
||
if type(lua_table) == "userdata" or type(lua_table) == "lightuserdata" or type(lua_table) == "thread" then
|
||
return tostring(lua_table)
|
||
end
|
||
|
||
if type(lua_table) == "string" or type(lua_table) == "number" then
|
||
return "[No-Table]:" .. lua_table
|
||
end
|
||
|
||
for k, v in pairs(lua_table) do
|
||
if k ~= "_class_type" then
|
||
local szBuffer = ""
|
||
Typev = type(v)
|
||
if Typev == "table" then
|
||
szBuffer = "{"
|
||
end
|
||
local szPrefix = string.rep(" ", indent)
|
||
if Typev == "table" and v._fields then
|
||
local kk, vv = next(v._fields)
|
||
if type(vv) == "table" then
|
||
content = content .. "\n\t" .. kk.name .. "={" .. LuaPrint(vv._fields, 5, indent + 1, step + 1) ..
|
||
"}"
|
||
else
|
||
content = content .. "\n\t" .. kk.name .. "=" .. vv
|
||
end
|
||
else
|
||
if type(k) == "table" then
|
||
if k.name then
|
||
if type(v) ~= "table" then
|
||
content = content .. "\n" .. k.name .. "=" .. v
|
||
else
|
||
content = content .. "\n" .. k.name .. " = list:"
|
||
local tmp = "\n"
|
||
for ka, va in ipairs(v) do
|
||
tmp = tmp .. "#" .. ka .. "_" .. tostring(va)
|
||
end
|
||
content = content .. tmp
|
||
end
|
||
end
|
||
elseif type(k) == "function" then
|
||
content = content .. "\n fun=function"
|
||
else
|
||
formatting = szPrefix .. tostring(k) .. " = " .. szBuffer
|
||
if Typev == "table" then
|
||
content = content .. "\n" .. formatting
|
||
content = content .. LuaPrint(v, limit, indent + 1, step + 1)
|
||
content = content .. "\n" .. szPrefix .. "},"
|
||
else
|
||
local szValue = ""
|
||
if Typev == "string" then
|
||
szValue = string.format("%q", v)
|
||
else
|
||
szValue = tostring(v)
|
||
end
|
||
content = content .. "\n" .. formatting .. (szValue or "nil") .. ","
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
return content
|
||
end
|
||
|
||
function printlog(...)
|
||
if debug_print then
|
||
print(...)
|
||
end
|
||
end
|
||
|
||
function PrintStackTrace(ignoreCount, options)
|
||
-- 默认参数
|
||
ignoreCount = ignoreCount or 3
|
||
options = options or {}
|
||
|
||
-- 合并配置选项
|
||
local config = {
|
||
maxDepth = options.maxDepth or 20,
|
||
indentSize = options.indentSize or 2,
|
||
showVariables = options.showVariables ~= false, -- 默认true
|
||
maxVariableLength = options.maxVariableLength or 50,
|
||
showLineNumbers = options.showLineNumbers ~= false,
|
||
showFunctionType = options.showFunctionType ~= false,
|
||
showFullPath = options.showFullPath or false,
|
||
colorOutput = options.colorOutput or false,
|
||
skipDebuggerFrames = options.skipDebuggerFrames ~= false,
|
||
debuggerFiles = options.debuggerFiles or {
|
||
"debugger.lua",
|
||
"LuaDebugger.lua",
|
||
"=[C]"
|
||
},
|
||
includeTimestamp = options.includeTimestamp or false,
|
||
maxStackDepth = options.maxStackDepth or 100
|
||
}
|
||
|
||
-- ANSI颜色代码(用于彩色输出)
|
||
local colors = {
|
||
reset = "\27[0m",
|
||
red = "\27[31m",
|
||
green = "\27[32m",
|
||
yellow = "\27[33m",
|
||
blue = "\27[34m",
|
||
magenta = "\27[35m",
|
||
cyan = "\27[36m",
|
||
white = "\27[37m",
|
||
gray = "\27[90m"
|
||
}
|
||
|
||
-- 如果不支持彩色输出,使用空字符串
|
||
if not config.colorOutput then
|
||
for k, _ in pairs(colors) do
|
||
colors[k] = ""
|
||
end
|
||
end
|
||
|
||
-- 辅助函数:判断是否为调试器自身的帧
|
||
local function isDebuggerFrame(frameInfo)
|
||
if not config.skipDebuggerFrames then
|
||
return false
|
||
end
|
||
|
||
for _, pattern in ipairs(config.debuggerFiles) do
|
||
if frameInfo.src and frameInfo.src:find(pattern, 1, true) then
|
||
return true
|
||
end
|
||
if frameInfo.source and frameInfo.source:find(pattern, 1, true) then
|
||
return true
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
-- 辅助函数:格式化变量值(限制长度)
|
||
local function formatValue(value, maxLength)
|
||
if value == nil then
|
||
return colors.gray .. "nil" .. colors.reset
|
||
end
|
||
|
||
local valueType = type(value)
|
||
local str
|
||
|
||
if valueType == "string" then
|
||
str = colors.green .. string.format("%q", value) .. colors.reset
|
||
elseif valueType == "number" then
|
||
str = colors.yellow .. tostring(value) .. colors.reset
|
||
elseif valueType == "boolean" then
|
||
str = colors.cyan .. tostring(value) .. colors.reset
|
||
elseif valueType == "table" then
|
||
local mt = getmetatable(value)
|
||
if mt and mt.__tostring then
|
||
str = tostring(value)
|
||
else
|
||
str = colors.magenta .. string.format("table: %p", value) .. colors.reset
|
||
end
|
||
elseif valueType == "function" then
|
||
str = colors.blue .. string.format("function: %p", value) .. colors.reset
|
||
elseif valueType == "userdata" or valueType == "thread" then
|
||
str = colors.white .. string.format("%s: %p", valueType, value) .. colors.reset
|
||
else
|
||
str = colors.gray .. tostring(value) .. colors.reset
|
||
end
|
||
|
||
-- 限制长度
|
||
if #str > maxLength * 2 then -- 乘以2因为ANSI代码也占长度
|
||
str = str:sub(1, maxLength * 2) .. "..."
|
||
end
|
||
|
||
return str
|
||
end
|
||
|
||
-- 辅助函数:格式化变量信息
|
||
local function formatVariables(vars, indent)
|
||
if not vars or not config.showVariables then
|
||
return ""
|
||
end
|
||
|
||
local lines = {}
|
||
local prefix = string.rep(" ", indent)
|
||
|
||
-- 处理局部变量
|
||
if vars.locals then
|
||
local hasLocals = false
|
||
local localNames = {}
|
||
for name, _ in pairs(vars.locals) do
|
||
table.insert(localNames, name)
|
||
end
|
||
table.sort(localNames) -- 按字母顺序排序
|
||
|
||
for _, name in ipairs(localNames) do
|
||
local info = vars.locals[name]
|
||
if not hasLocals then
|
||
table.insert(lines, prefix .. colors.cyan .. "Local Variables:" .. colors.reset)
|
||
hasLocals = true
|
||
end
|
||
local valueStr = formatValue(info.value, config.maxVariableLength)
|
||
table.insert(lines, string.format("%s %s%s%s = %s",
|
||
prefix, colors.yellow, name, colors.reset, valueStr))
|
||
end
|
||
end
|
||
|
||
-- 处理上值(upvalues)
|
||
if vars.upvalues then
|
||
local hasUpvalues = false
|
||
local upvalueNames = {}
|
||
for name, _ in pairs(vars.upvalues) do
|
||
table.insert(upvalueNames, name)
|
||
end
|
||
table.sort(upvalueNames)
|
||
|
||
for _, name in ipairs(upvalueNames) do
|
||
local info = vars.upvalues[name]
|
||
if not hasUpvalues then
|
||
table.insert(lines, prefix .. colors.cyan .. "Upvalues:" .. colors.reset)
|
||
hasUpvalues = true
|
||
end
|
||
local valueStr = formatValue(info.value, config.maxVariableLength)
|
||
table.insert(lines, string.format("%s %s%s%s = %s",
|
||
prefix, colors.yellow, name, colors.reset, valueStr))
|
||
end
|
||
end
|
||
|
||
if #lines > 0 then
|
||
return table.concat(lines, "\n") .. "\n"
|
||
end
|
||
return ""
|
||
end
|
||
|
||
-- 获取堆栈信息
|
||
local stackInfo = {}
|
||
local outputLines = {}
|
||
|
||
-- 添加标题
|
||
if config.includeTimestamp then
|
||
table.insert(outputLines, colors.white .. "=== Stack Trace @" .. os.date("%H:%M:%S") .. " ===" .. colors.reset)
|
||
else
|
||
table.insert(outputLines, colors.white .. "=== Stack Trace ===" .. colors.reset)
|
||
end
|
||
|
||
-- 收集堆栈信息
|
||
local frameCount = 0
|
||
local skippedDebuggerFrames = 0
|
||
|
||
for level = ignoreCount, config.maxStackDepth do
|
||
local source = debug.getinfo(level, "Snlf")
|
||
if not source then
|
||
break
|
||
end
|
||
|
||
-- 构建栈帧信息
|
||
local frameInfo = {
|
||
level = level - ignoreCount + 1,
|
||
src = source.source,
|
||
funcName = source.name or "<anonymous>",
|
||
currentline = source.currentline,
|
||
linedefined = source.linedefined,
|
||
lastlinedefined = source.lastlinedefined,
|
||
what = source.what,
|
||
namewhat = source.namewhat or "",
|
||
source = source.source
|
||
}
|
||
|
||
-- 跳过调试器自身的帧
|
||
if isDebuggerFrame(frameInfo) then
|
||
skippedDebuggerFrames = skippedDebuggerFrames + 1
|
||
goto continue
|
||
end
|
||
|
||
-- 达到最大显示深度时停止
|
||
if frameCount >= config.maxDepth then
|
||
table.insert(outputLines, colors.gray .. string.format("... (%d more frames hidden)",
|
||
(config.maxStackDepth - level + 1)) .. colors.reset)
|
||
break
|
||
end
|
||
|
||
-- 格式化文件路径
|
||
local filePath
|
||
if config.showFullPath then
|
||
filePath = source.source
|
||
else
|
||
-- 提取文件名
|
||
if source.source:sub(1, 1) == "@" then
|
||
local path = source.source:sub(2)
|
||
local _, filename = path:match("^.*[/\\](.+)$")
|
||
filePath = filename or path
|
||
elseif source.source:sub(1, 1) == "=" then
|
||
filePath = source.source:sub(2)
|
||
else
|
||
filePath = "[string]"
|
||
end
|
||
end
|
||
|
||
-- 构建帧描述
|
||
local indent = string.rep(" ", config.indentSize)
|
||
local framePrefix = string.format("#%d ", frameCount + 1)
|
||
|
||
local frameLine
|
||
if config.showLineNumbers then
|
||
if source.currentline > 0 then
|
||
frameLine = string.format("%s%s in %s%s%s at %s%s%s:%s%d%s",
|
||
colors.white, framePrefix,
|
||
colors.yellow, frameInfo.funcName, colors.reset,
|
||
colors.blue, filePath, colors.reset,
|
||
colors.green, source.currentline, colors.reset)
|
||
else
|
||
frameLine = string.format("%s%s in %s%s%s at %s%s%s",
|
||
colors.white, framePrefix,
|
||
colors.yellow, frameInfo.funcName, colors.reset,
|
||
colors.blue, filePath, colors.reset)
|
||
end
|
||
else
|
||
frameLine = string.format("%s%s in %s%s%s",
|
||
colors.white, framePrefix,
|
||
colors.yellow, frameInfo.funcName, colors.reset)
|
||
end
|
||
|
||
-- 添加函数类型信息
|
||
if config.showFunctionType then
|
||
local typeColor = colors.gray
|
||
if source.what == "Lua" then
|
||
typeColor = colors.green
|
||
elseif source.what == "C" then
|
||
typeColor = colors.red
|
||
elseif source.what == "main" then
|
||
typeColor = colors.cyan
|
||
end
|
||
|
||
frameLine = frameLine .. string.format(" [%s%s%s]",
|
||
typeColor, source.what, colors.reset)
|
||
end
|
||
|
||
table.insert(outputLines, frameLine)
|
||
|
||
-- 获取并格式化变量
|
||
if config.showVariables then
|
||
local success, vars = pcall(function()
|
||
local varInfo = {}
|
||
|
||
-- 获取局部变量
|
||
varInfo.locals = {}
|
||
local idx = 1
|
||
while true do
|
||
local name, value = debug.getlocal(level + 1, idx)
|
||
if not name then break end
|
||
|
||
-- 过滤掉调试器内部变量
|
||
if not name:find("^_debugger_") then
|
||
varInfo.locals[name] = {
|
||
value = value,
|
||
type = type(value)
|
||
}
|
||
end
|
||
idx = idx + 1
|
||
end
|
||
|
||
-- 获取上值
|
||
varInfo.upvalues = {}
|
||
local func = debug.getinfo(level + 1, "f").func
|
||
if func then
|
||
idx = 1
|
||
while true do
|
||
local name, value = debug.getupvalue(func, idx)
|
||
if not name then break end
|
||
|
||
varInfo.upvalues[name] = {
|
||
value = value,
|
||
type = type(value)
|
||
}
|
||
idx = idx + 1
|
||
end
|
||
end
|
||
|
||
return varInfo
|
||
end)
|
||
|
||
if success then
|
||
local varsStr = formatVariables(vars, config.indentSize * 2)
|
||
if varsStr ~= "" then
|
||
table.insert(outputLines, varsStr)
|
||
end
|
||
end
|
||
end
|
||
|
||
frameCount = frameCount + 1
|
||
|
||
-- 到达主程序层时停止
|
||
if source.what == "main" then
|
||
break
|
||
end
|
||
|
||
::continue::
|
||
end
|
||
|
||
-- 添加统计信息
|
||
table.insert(outputLines, "")
|
||
table.insert(outputLines, colors.gray .. string.format(
|
||
"Total frames: %d (skipped %d debugger frames)",
|
||
frameCount, skippedDebuggerFrames) .. colors.reset)
|
||
|
||
-- 如果没有找到任何帧
|
||
if frameCount == 0 then
|
||
table.insert(outputLines,
|
||
colors.yellow .. "No stack frames found (possibly all frames were skipped)" .. colors.reset)
|
||
end
|
||
|
||
-- 添加分隔线
|
||
table.insert(outputLines, colors.white .. "====================" .. colors.reset)
|
||
|
||
return table.concat(outputLines, "\n")
|
||
end
|
||
|
||
function InnerFunction()
|
||
local x = 42
|
||
local name = "Test"
|
||
local data = { a = 1, b = 2 }
|
||
|
||
-- 打印堆栈信息
|
||
local trace = PrintStackTrace(2, {
|
||
showVariables = false,
|
||
colorOutput = false,
|
||
maxDepth = 20
|
||
})
|
||
|
||
return trace
|
||
end
|
||
|