1 QuestHelper_File
["collect.lua"] = "Development Version"
2 QuestHelper_Loadtime
["collect.lua"] = GetTime()
4 local debug_output
= false
5 if QuestHelper_File
["collect.lua"] == "Development Version" then debug_output
= true end
7 local QuestHelper_Collector_Version_Current
= 8
9 QuestHelper_Collector
= {}
10 QuestHelper_Collector_Version
= QuestHelper_Collector_Version_Current
12 local OnUpdateRegistrar
= {}
13 local TooltipRegistrar
= {}
15 local function OnUpdateHookRegistrar(func
)
16 QuestHelper
: Assert(func
)
17 table.insert(OnUpdateRegistrar
, func
)
20 local suppress
= false
22 -- real tooltips don't use this function
23 local SetTextScript
= GameTooltip
.SetText
24 GameTooltip
.SetText
= function (...)
30 local function CollectTooltippery(self
)
31 if not self
then self
= GameTooltip
end
33 for k
, v
in pairs(TooltipRegistrar
) do
37 -- anything past here is not my fault
40 local ottsu
= GameTooltip
:GetScript("OnTooltipSetUnit")
41 QH_Hook(GameTooltip
, "OnTooltipSetUnit", function (self
, ...)
42 CollectTooltippery(self
)
43 if ottsu
then return QH_Hook_NotMyFault(ottsu
, self
, ...) end
44 end, "collection OnTooltipSetUnit")
46 local ottsi
= GameTooltip
:GetScript("OnTooltipSetItem")
47 QH_Hook(GameTooltip
, "OnTooltipSetItem", function (self
, ...)
48 CollectTooltippery(self
)
49 if ottsi
then return QH_Hook_NotMyFault(ottsi
, self
, ...) end
50 end, "collection OnTooltipSetItem")
52 local ottsh
= GameTooltip
:GetScript("OnShow")
53 QH_Hook(GameTooltip
, "OnShow", function (self
, ...)
54 CollectTooltippery(self
)
55 if ottsh
then return QH_Hook_NotMyFault(ottsh
, self
, ...) end
56 end, "collection OnShow")
59 local function TooltipHookRegistrar(func
)
60 QuestHelper
: Assert(func
)
61 table.insert(TooltipRegistrar
, func
)
65 Registrar_OnUpdateHook
= OnUpdateHookRegistrar
,
66 Registrar_TooltipHook
= TooltipHookRegistrar
,
67 Callback_Location_Raw
= function () return QuestHelper
:Location_RawRetrieve() end,
68 Callback_Location_Absolute
= function () return QuestHelper
:Location_AbsoluteRetrieve() end,
71 -- We do these early, because some things that aren't in collect may rely on these. Yes I realize that avoiding this was one of my main goals in the separate collect system, shut up go away I hate you (in all seriousness: crunch mode + lazy = some nasty bits.)
72 -- TODO: Make a common collect/mainmodule system, then rely on that better.
73 QH_Collect_Util_Init(nil, API
) -- Some may actually add their own functions to the API, and should go first. There's no real formalized order, I just know which depend on others, and it's heavily asserted so it will break if it goes in the wrong order.
74 QH_Collect_Merger_Init(nil, API
)
75 QH_Collect_Bitstream_Init(nil, API
)
76 QH_Collect_Location_Init(nil, API
)
77 QH_Collect_Patterns_Init(nil, API
)
78 QH_Collect_Notifier_Init(nil, API
)
79 QH_Collect_Spec_Init(nil, API
)
80 QH_Collect_LZW_Init(nil, API
)
82 local CompressCollection
84 function QH_Collector_Init()
85 QH_Collector_UpgradeAll(QuestHelper_Collector
)
87 for _
, v
in pairs(QuestHelper_Collector
) do
88 if not v
.modified
then v
.modified
= time() - 7 * 24 * 60 * 60 end -- eugh. Yeah, we set it to be a week ago. It's pretty grim.
91 QuestHelper_Collector_Version
= QuestHelper_Collector_Version_Current
93 local sig
= string.format("%s on %s/%s/%d", GetAddOnMetadata("QuestHelper", "Version"), GetBuildInfo(), GetLocale(), QuestHelper
:PlayerFaction())
94 local sig_altfaction
= string.format("%s on %s/%s/%d", GetAddOnMetadata("QuestHelper", "Version"), GetBuildInfo(), GetLocale(), (QuestHelper
:PlayerFaction() == 1) and 2 or 1)
95 if not QuestHelper_Collector
[sig
] or QuestHelper_Collector
[sig
].compressed
then QuestHelper_Collector
[sig
] = {version
= QuestHelper_Collector_Version
} end -- fuckin' bullshit, man
96 local QHCData
= QuestHelper_Collector
[sig
]
97 QuestHelper
: Assert(not QHCData
.compressed
)
98 QuestHelper
: Assert(QHCData
.version
== QuestHelper_Collector_Version_Current
)
99 QHCData
.modified
= time()
101 QH_Collect_Achievement_Init(QHCData
, API
)
102 QH_Collect_Traveled_Init(QHCData
, API
)
103 QH_Collect_Zone_Init(QHCData
, API
)
104 QH_Collect_Monster_Init(QHCData
, API
)
105 QH_Collect_Item_Init(QHCData
, API
)
106 QH_Collect_Object_Init(QHCData
, API
)
107 QH_Collect_Flight_Init(QHCData
, API
)
108 QH_Collect_Quest_Init(QHCData
, API
)
109 QH_Collect_Warp_Init(QHCData
, API
)
111 QH_Collect_Loot_Init(QHCData
, API
)
112 QH_Collect_Equip_Init(QHCData
, API
)
113 QH_Collect_Merchant_Init(QHCData
, API
)
115 if not QHCData
.realms
then QHCData
.realms
= {} end
116 QHCData
.realms
[GetRealmName()] = (QHCData
.realms
[GetRealmName()] or 0) + 1 -- I'm not entirely sure why I'm counting
118 if false then -- this will be disabled in most public releases, or set to a very rare probabalistic thing
119 if not QHCData
.routing_dump
then QHCData
.routing_dump
= {} end
121 table.insert(QHCData
.routing_dump
, nt
)
122 QH_Collect_Routing_Dump
= nt
125 do -- Clean some stuff up!
126 local obliterate
= {}
127 for k
, v
in pairs(QuestHelper_Collector
) do
128 if not v
.modified
or v
.modified
+ 30 * 24 * 60 * 60 < GetTime() then
129 table.insert(obliterate
, k
)
133 for _
, v
in ipairs(obliterate
) do
134 QuestHelper_Collector
[v
] = nil
138 -- So, why do we delay it?
139 -- It's simple. People are gonna update to this version, and then they're going to look at the memory usage. Then they will panic because omg this version uses so much more memory, I bet that will somehow hurt my framerates in a way which is not adequately explained!
140 -- So instead, we just wait half an hour before compressing. Compression will still get done, and I won't have to deal with panicked comments about how bloated QH has gotten.
141 -- addendum: yeah naturally I'm getting all sorts of panicked comments about how bloated qh has gotten, sigh
142 API
.Utility_Notifier(GetTime() + (debug_output
and 0 or (30 * 60)), function() CompressCollection(QHCData
, QuestHelper_Collector
[sig_altfaction
], API
.Utility_Merger
, API
.Utility_LZW
.Compress
) end)
145 QH_OnUpdate(function ()
146 local tstart
= GetTime()
147 for _
, v
in pairs(OnUpdateRegistrar
) do
150 QH_Timeslice_Increment(GetTime() - tstart
, "collect_update")
155 --- I've tossed the compression stuff down here just 'cause I don't feel like making an entire file for it (even though I probably should.)
157 local noncompressible
= {
166 local serializers
= {
167 ["nil"] = function(item
, add
)
170 ["number"] = function(item
, add
)
173 ["string"] = function(item
, add
)
174 add(string.format("%q", item
))
176 ["boolean"] = function(item
, add
)
177 add(item
and "true" or "false")
179 ["table"] = function(item
, add
)
182 for k
, v
in pairs(item
) do
183 if not first
then add(",") end
194 seritem
= function(item
, add
)
196 serializers
[type(item
)](item
, add
)
199 local function DoCompress(item
, merger
, comp
)
200 if debug_output
then QuestHelper
: TextOut("Item condensing") end
204 for k
, v
in pairs(item
) do
205 if not noncompressible
[k
] then
211 seritem(target
, function(dat
) merger
.Add(mg
, dat
) end)
213 local tg
= merger
.Finish(mg
)
214 if debug_output
then QuestHelper
: TextOut(string.format("Item condensed to %d bytes, %f taken so far", #tg
, GetTime() - ts
)) end
220 local doublecheck
= ""
221 for chunk
= 1, #tg
, 1048576 do
222 local fragment
= tg
:sub(chunk
, chunk
+ 1048575)
223 doublecheck
= doublecheck
.. fragment
224 local ite
= comp(fragment
, 256, 8)
225 cmptot
= cmptot
+ #ite
226 table.insert(cmp
, ite
)
228 QuestHelper
: Assert(doublecheck
== tg
)
230 if #cmp
== 1 then cmp
= cmp
[1] end
232 for k
, v
in pairs(target
) do
233 if not noncompressible
[k
] then
237 item
.compressed
= cmp
239 if debug_output
then QuestHelper
: TextOut(string.format("Item compressed to %d bytes in %d shards (previously %d), %f taken", cmptot
, type(cmp
) == "table" and #cmp
or 1, #tg
, GetTime() - ts
)) end
242 CompressCollection
= function(active
, active2
, merger
, comp
)
243 for _
, v
in pairs(QuestHelper_Collector
) do
244 if v
~= active
and v
~= active2
and not v
.compressed
then
245 QH_Timeslice_Add(function ()
246 DoCompress(v
, merger
, comp
)
247 CompressCollection(active
, active2
, merger
, comp
)