Files
GaCy-GO/tools/gacha_live_clone_probe.lua
T
2026-10-28 18:54:43 +07:00

93 lines
3.7 KiB
Lua

-- Inactive research tool: stage only when the Client is walking, then remove.
-- Never mutates a live pool, config row, module list or dictionary. Clones use
-- the same MemberwiseClone/5-argument Invoke path as navigation_profiles.lua.
do
local function capture()
local s=_G.__GAC_GACHA_LIVE_CLONE1 or {phase=1}
_G.__GAC_GACHA_LIVE_CLONE1=s
if s.phase>4 then return end
local log=function(x)CS.UnityEngine.Debug.Log('[GAC_GACHA_LIVE_CLONE] '..tostring(x))end
local flags=CS.System.Enum.ToObject(typeof(CS.System.Reflection.BindingFlags),60)
local invoke=CS.System.Enum.ToObject(typeof(CS.System.Reflection.BindingFlags),0)
local manager=CS.RPG.Client.GlobalVars.s_GamePhaseManager
local phase=manager and typeof(CS.RPG.Client.GamePhaseManager):GetField('_CurrentPhase',flags):GetValue(manager)
if not phase or typeof(CS.RPG.Client.BattleGamePhase):IsInstanceOfType(phase) then return end
if s.phase==1 then
local page=package.loaded['Ui.Gacha.GachaMainPage']
if type(page)=='table' and type(page._create_pools_panel)=='function' then
for i=1,16 do
local name,value=debug.getupvalue(page._create_pools_panel,i)
if name==nil then break end
if name=='_gacha_module' then s.module=value;break end
end
end
if not s.module then s.module=CS.RPG.Client.GlobalVars.s_ModuleManager.GachaModule end
if not s.module then return end
local pools=s.module:GetSortedGachaPoolDatas()
if not pools or pools.Count==0 then return end
s.template=pools[0]
s.clone=typeof(CS.System.Object):GetMethod('MemberwiseClone',flags)
s.empty=CS.System.Array.CreateInstance(typeof(CS.System.Object),0)
s.pool=s.clone:Invoke(s.template,invoke,nil,s.empty,nil)
s.row=s.clone:Invoke(s.template.Row,invoke,nil,s.empty,nil)
local base=s.template:GetType()
while base and base.FullName~='RPG.Client.BaseGachaPoolData' do base=base.BaseType end
if not base then error('pool base type absent') end
s.base=base
base:GetField('<Row>k__BackingField',flags):SetValue(s.pool,s.row)
if s.pool==s.template or s.row==s.template.Row or s.pool.GachaID~=s.template.GachaID then
error('detached clone identity failed')
end
log('DETACHED_OK concrete='..s.pool:GetType().FullName..' id='..s.pool.GachaID..' prefab='..s.pool.PrefabPath)
s.phase=2
return
end
if s.phase==2 then
local types={s.pool:GetType(),s.base}
for _,t in ipairs(types) do
log('TYPE '..t.FullName)
local fs=t:GetFields(flags)
for i=0,math.min(fs.Length-1,47) do
local f=fs[i]
if f.DeclaringType==t and not f.IsStatic then log('FIELD '..f.Name..' '..f.FieldType.FullName) end
end
end
s.phase=3
return
end
if s.phase==3 then
local groups=s.module:GetSortedGachaGroupDatas()
if not groups or groups.Count==0 then error('no initialized groups') end
local group=groups[0]
local t=group:GetType()
log('GROUP concrete='..t.FullName..' id='..group.GroupID)
for depth=1,3 do
if not t or t.FullName=='System.Object' then break end
log('TYPE '..t.FullName)
local fs=t:GetFields(flags)
for i=0,math.min(fs.Length-1,47) do
local f=fs[i]
if f.DeclaringType==t and not f.IsStatic then log('FIELD '..f.Name..' '..f.FieldType.FullName) end
end
t=t.BaseType
end
s.phase=4
return
end
local methods=s.module:GetType():GetMethods(flags)
for i=0,methods.Length-1 do
local m=methods[i]
if m.Name=='_AddGachaPoolDataToGroupDict' then
log('REGISTER_SIGNATURE '..tostring(m))
end
end
log('END no registration or live mutation performed')
s.module=nil;s.template=nil;s.pool=nil;s.row=nil;s.base=nil;s.phase=5
end
local ok,err=pcall(capture)
if not ok then
_G.__GAC_GACHA_LIVE_CLONE1={phase=99}
CS.UnityEngine.Debug.Log('[GAC_GACHA_LIVE_CLONE] ERROR '..tostring(err))
end
end