118 lines
5.2 KiB
Lua
118 lines
5.2 KiB
Lua
-- Read-only, bounded Tea Break investigation. Keep outside scripts/ until an
|
|||
|
|
-- operator deliberately stages it. Does not send packets or change UI/state.
|
||
|
|
do local function capture()
|
||
|
|
local state=_G.__gacCwTeaBreakRuntime2
|
||
|
|
if not state then
|
||
|
|
state={step=1,index=0,beats=0};_G.__gacCwTeaBreakRuntime2=state
|
||
|
|
end
|
||
|
|
if state.done then return end
|
||
|
|
state.beats=state.beats+1
|
||
|
|
local function log(s)CS.UnityEngine.Debug.Log('[GAC_CW_TEA_RUNTIME2] '..tostring(s))end
|
||
|
|
if state.beats>36 then state.done=true;log('END beat budget');return end
|
||
|
|
local flags=CS.System.Enum.ToObject(typeof(CS.System.Reflection.BindingFlags),60)
|
||
|
|
local gm=CS.RPG.Client.GlobalVars.s_GamePhaseManager
|
||
|
|
local current=gm and gm:GetType():GetField('_CurrentPhase',flags)
|
||
|
|
local phase=current and current:GetValue(gm)
|
||
|
|
if not phase then log('WAIT game phase');return end
|
||
|
|
if typeof(CS.RPG.Client.BattleGamePhase):IsInstanceOfType(phase)then return end
|
||
|
|
if state.step==1 then
|
||
|
|
local t=typeof(CS.RPG.Client.GridFightModule)
|
||
|
|
local p=t:GetProperty('Instance',flags)
|
||
|
|
if p then local ok,obj=pcall(function()return p:GetValue(nil,nil)end);if ok then state.module=obj end end
|
||
|
|
if not state.module then
|
||
|
|
local manager=CS.RPG.Client.GlobalVars.s_ModuleManager
|
||
|
|
if manager then local ok,obj=pcall(function()return manager.GridFightModule end);if ok then state.module=obj end end
|
||
|
|
end
|
||
|
|
log('MODULE '..tostring(state.module and state.module:GetType().FullName))
|
||
|
|
state.session=state.module and state.module.CurGameSession
|
||
|
|
local sf=state.session and state.session:GetType():GetField('_GameEventData',flags)
|
||
|
|
state.event=sf and sf:GetValue(state.session)
|
||
|
|
log('EVENT_TYPE '..tostring(state.event and state.event:GetType().FullName))
|
||
|
|
local stage=state.session and state.session.Stage
|
||
|
|
local node=stage and stage.CurNode
|
||
|
|
if node then
|
||
|
|
log('NODE route='..tostring(stage.RouteID)..' chapter='..tostring(stage.ChapterID)..' section='..tostring(stage.SectionID)..' bonfire='..tostring(node.IsBonfireNode))
|
||
|
|
local ids=node.BonfireEventIds
|
||
|
|
if ids then
|
||
|
|
if ids.Count>16 then error('bonfire event bound')end
|
||
|
|
for i=0,ids.Count-1 do log('BONFIRE_EVENT '..tostring(ids[i]))end
|
||
|
|
end
|
||
|
|
local nf=node:GetType():GetField('_NodeParam',flags)
|
||
|
|
local param=nf and nf:GetValue(node)
|
||
|
|
if param then
|
||
|
|
local raw=CS.Newtonsoft.Json.JsonConvert.SerializeObject(param)
|
||
|
|
if #raw>16384 then error('node parameter bound')end
|
||
|
|
log('NODE_PARAM '..raw)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
state.types={t.Assembly:GetType('RPG.Client.GridFightGameEventData'),t.Assembly:GetType('RPG.Client.GridFightStageNode')}
|
||
|
|
state.typeindex=1;state.step=2;return
|
||
|
|
end
|
||
|
|
if state.step==2 then
|
||
|
|
local t=state.types[state.typeindex]
|
||
|
|
if not t then state.typeindex=state.typeindex+1;if state.typeindex>2 then state.step=3 end;return end
|
||
|
|
if not state.methods then
|
||
|
|
log('TYPE '..t.FullName)
|
||
|
|
if state.typeindex==2 then
|
||
|
|
for _,name in ipairs({'_RefreshBonfireEventIds','get_IsBonfireNode','get_BonfireEventIds'})do
|
||
|
|
local m=t:GetMethod(name,flags)
|
||
|
|
if m then log('METHOD '..tostring(m)..' HANDLE '..tostring(m.MethodHandle.Value))end
|
||
|
|
end
|
||
|
|
state.step=3;return
|
||
|
|
end
|
||
|
|
state.methods=t:GetMethods(flags);state.fields=t:GetFields(flags);state.index=0
|
||
|
|
end
|
||
|
|
for i=state.index,math.min(state.index+7,state.methods.Length-1)do
|
||
|
|
local m=state.methods[i]
|
||
|
|
if m.DeclaringType==t then
|
||
|
|
local n=m.Name:lower()
|
||
|
|
if state.typeindex==1 or n:find('bonfire')then log('METHOD '..tostring(m)..' HANDLE '..tostring(m.MethodHandle.Value))end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
state.index=state.index+8
|
||
|
|
if state.index>=state.methods.Length then state.step=4;state.index=0 end
|
||
|
|
return
|
||
|
|
end
|
||
|
|
if state.step==4 then
|
||
|
|
local t=state.types[state.typeindex]
|
||
|
|
for i=state.index,math.min(state.index+7,state.fields.Length-1)do
|
||
|
|
local f=state.fields[i]
|
||
|
|
if f.DeclaringType==t and not f.IsStatic then
|
||
|
|
log('FIELD '..tostring(f))
|
||
|
|
if state.typeindex==1 and state.event then
|
||
|
|
local v=f:GetValue(state.event)
|
||
|
|
if v==nil then log('VALUE '..f.Name..'=nil')
|
||
|
|
elseif f.FieldType.IsPrimitive or f.FieldType.IsEnum or f.FieldType.FullName=='System.String' then log('VALUE '..f.Name..'='..tostring(v))
|
||
|
|
else log('VALUE_TYPE '..f.Name..' '..v:GetType().FullName)end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
state.index=state.index+8
|
||
|
|
if state.index>=state.fields.Length then
|
||
|
|
state.typeindex=state.typeindex+1;state.methods=nil;state.fields=nil;state.index=0
|
||
|
|
state.step=state.typeindex>2 and 3 or 2
|
||
|
|
end
|
||
|
|
return
|
||
|
|
end
|
||
|
|
if state.step==3 then
|
||
|
|
local page=CS.RPG.Client.GlobalVars.s_UIManager:GetPageByName('GridFightPreparationPage')
|
||
|
|
local obj=page and page.LuaTable
|
||
|
|
if type(obj)=='table'then
|
||
|
|
local names={'_on_start_battle_click','_enter_battle','_check_enter_battle_by_reason'}
|
||
|
|
for _,name in ipairs(names)do
|
||
|
|
local fn=obj[name]
|
||
|
|
if type(fn)=='function'then
|
||
|
|
log('LUA_FUNCTION '..name)
|
||
|
|
for i=1,24 do
|
||
|
|
local key,val=debug.getupvalue(fn,i);if not key then break end
|
||
|
|
log('LUA_UPVALUE '..name..' '..i..' '..key..' '..type(val))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else log('NO preparation page')end
|
||
|
|
state.done=true;state.module=nil;state.session=nil;state.event=nil;log('END')
|
||
|
|
end
|
||
|
|
end
|
||
|
|
local ok,e=pcall(capture)
|
||
|
|
if not ok then _G.__gacCwTeaBreakRuntime2={done=true};CS.UnityEngine.Debug.Log('[GAC_CW_TEA_RUNTIME2] ERROR '..tostring(e))end
|
||
|
|
end
|