Repository navigation
Expand file tree
/
Copy pathInit.lua
More file actions
356 lines (298 loc) · 11 KB
/
Copy pathInit.lua
File metadata and controls
356 lines (298 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
-- HealIQ Init.lua
-- Robust addon initialization system to prevent TOC loading errors
--
-- This module provides:
-- * Event-driven initialization that doesn't depend on loading order
-- * Robust error recovery for failed file loading
-- * WoW API availability checking before initialization
-- * Registry system for components to self-register
-- * Comprehensive logging of initialization process
-- Robust parameter handling - works regardless of loading order
local addonName, addonTable = ...
-- Validate addon parameters - WoW passes addon name and table, but be defensive
-- addonName is used later to set HealIQ.addonName (see line 37 in initializeCore)
if type(addonName) ~= "string" then
addonName = "HealIQ" -- Fallback to hardcoded name if invalid
end
-- Create addon object if it doesn't exist, using the passed table or creating new one
-- We use a local variable first, then publish to global namespace after initialization
-- This prevents other code from accessing a half-initialized HealIQ object
local HealIQ = addonTable or {}
-- Global initialization registry
local InitRegistry = {
components = {},
initialized = false,
errors = {},
startTime = 0
}
-- Initialize the core HealIQ object with minimal required structure
local function initializeCore()
-- Ensure basic structure exists
HealIQ.version = HealIQ.version or "0.2.0"
HealIQ.addonName = addonName
HealIQ.debug = HealIQ.debug or false
-- Create namespaces
HealIQ.Rules = HealIQ.Rules or {}
HealIQ.Components = HealIQ.Components or {}
-- Core utility functions
HealIQ.SafeCall = HealIQ.SafeCall or function(func, ...)
if type(func) ~= "function" then
return false, "Invalid function"
end
local success, result = pcall(func, ...)
if not success then
local errorMsg = tostring(result or "unknown error")
if HealIQ.debug and print then
print("|cFFFF0000HealIQ Init Error:|r " .. errorMsg)
end
return false, errorMsg
end
return success, result
end
-- Message function
HealIQ.Message = HealIQ.Message or function(message, isError)
-- Ensure message is converted to string, handle any type safely
local msgStr
if type(message) == "table" then
-- If it's a table, try to get a meaningful representation
msgStr = "(table error: " .. tostring(message) .. ")"
-- Try to extract error details if available
if HealIQ.debug and message.message and type(message.message) == "string" then
msgStr = msgStr .. " - " .. message.message
end
elseif message == nil then
msgStr = "(nil message)"
else
msgStr = tostring(message)
end
local prefix = isError and "|cFFFF0000HealIQ Error:|r " or "|cFF00FF00HealIQ:|r "
if print then
print(prefix .. msgStr)
end
end
-- Debug logging
HealIQ.DebugLog = HealIQ.DebugLog or function(message, level)
if HealIQ.debug and print then
local color = "|cFF888888"
if level == "ERROR" then color = "|cFFFF0000"
elseif level == "WARN" then color = "|cFFFFFF00"
elseif level == "INFO" then color = "|cFF00FF00"
end
print(color .. "[HealIQ Init] " .. tostring(message) .. "|r")
end
end
-- Global reference
_G.HealIQ = HealIQ
HealIQ:DebugLog("Core HealIQ object initialized", "INFO")
return true
end
-- Check if WoW API is available for safe initialization
local function checkWoWAPIAvailability()
local requiredFunctions = {
"CreateFrame",
"GetTime",
"UnitExists",
"IsInCombatLockdown"
}
local available = 0
local total = #requiredFunctions
for _, funcName in ipairs(requiredFunctions) do
if _G[funcName] and type(_G[funcName]) == "function" then
available = available + 1
end
end
return available >= (total * 0.75) -- 75% of functions must be available
end
-- Component registration system
function InitRegistry:RegisterComponent(name, initFunc, dependencies)
if type(name) ~= "string" or type(initFunc) ~= "function" then
HealIQ:DebugLog("Invalid component registration: " .. tostring(name), "ERROR")
return false
end
self.components[name] = {
name = name,
initFunc = initFunc,
dependencies = dependencies or {},
initialized = false,
error = nil,
retries = 0
}
HealIQ:DebugLog("Component registered: " .. name, "INFO")
-- Try immediate initialization if system is ready
if self.initialized then
self:InitializeComponent(name)
end
return true
end
-- Initialize a single component with dependency checking
function InitRegistry:InitializeComponent(name)
local component = self.components[name]
if not component then
HealIQ:DebugLog("Component not found: " .. name, "ERROR")
return false
end
if component.initialized then
return true
end
-- Check dependencies
for _, depName in ipairs(component.dependencies) do
local dep = self.components[depName]
if not dep or not dep.initialized then
HealIQ:DebugLog("Component " .. name .. " waiting for dependency: " .. depName, "WARN")
return false
end
end
-- Initialize component
HealIQ:DebugLog("Initializing component: " .. name, "INFO")
local success, error = HealIQ:SafeCall(component.initFunc)
if success then
component.initialized = true
HealIQ:DebugLog("Component initialized successfully: " .. name, "INFO")
return true
else
component.error = error
component.retries = component.retries + 1
table.insert(self.errors, {
component = name,
error = error,
retries = component.retries,
timestamp = GetTime and GetTime() or 0
})
HealIQ:DebugLog("Component initialization failed: " .. name .. " - " .. tostring(error), "ERROR")
-- Retry logic for recoverable errors
if component.retries < 3 and not string.find(tostring(error), "critical") then
HealIQ:DebugLog("Will retry component: " .. name, "WARN")
end
return false
end
end
-- Initialize all registered components
function InitRegistry:InitializeAll()
if self.initialized then
return
end
self.startTime = GetTime and GetTime() or 0
HealIQ:DebugLog("Starting component initialization", "INFO")
-- Multiple passes to handle dependencies
local maxPasses = 10
local pass = 1
repeat
local initializedThisPass = 0
local totalPending = 0
for name, component in pairs(self.components) do
if not component.initialized then
totalPending = totalPending + 1
if self:InitializeComponent(name) then
initializedThisPass = initializedThisPass + 1
end
end
end
pass = pass + 1
if initializedThisPass == 0 and totalPending > 0 then
HealIQ:DebugLog("No progress in initialization pass " .. (pass - 1) .. ", retrying failed components", "WARN")
-- Retry failed components
for name, component in pairs(self.components) do
if not component.initialized and component.retries < 3 then
self:InitializeComponent(name)
end
end
end
until initializedThisPass == 0 or totalPending == 0 or pass > maxPasses
self.initialized = true
-- Report results
local initialized = 0
local failed = 0
for name, component in pairs(self.components) do
if component.initialized then
initialized = initialized + 1
else
failed = failed + 1
HealIQ:DebugLog("Component failed to initialize: " .. name, "ERROR")
end
end
local endTime = GetTime and GetTime() or 0
local duration = endTime - self.startTime
HealIQ:Message(string.format("HealIQ initialization complete: %d successful, %d failed in %.2fs",
initialized, failed, duration))
if failed > 0 then
HealIQ:Message("Some components failed to initialize. Addon may have reduced functionality.", true)
end
end
-- Get initialization status
function InitRegistry:GetStatus()
local status = {
initialized = self.initialized,
totalComponents = 0,
initializedComponents = 0,
failedComponents = 0,
errors = self.errors,
startTime = self.startTime
}
for name, component in pairs(self.components) do
status.totalComponents = status.totalComponents + 1
if component.initialized then
status.initializedComponents = status.initializedComponents + 1
else
status.failedComponents = status.failedComponents + 1
end
end
return status
end
-- Initialize core system
local coreInitialized = false
local function performInitialization()
if coreInitialized then
return
end
-- Initialize core HealIQ object
local coreSuccess, coreError = pcall(initializeCore)
if not coreSuccess then
if print then print("|cFFFF0000HealIQ Critical Error:|r Failed to initialize core object - " .. tostring(coreError)) end
return
end
-- Check WoW API availability
if not checkWoWAPIAvailability() then
if HealIQ.DebugLog then
HealIQ:DebugLog("WoW API not fully available yet, deferring initialization", "WARN")
end
-- Try again later
if C_Timer and C_Timer.After then
C_Timer.After(0.1, performInitialization)
end
return
end
coreInitialized = true
if HealIQ.DebugLog then
HealIQ:DebugLog("Core initialization complete, starting component initialization", "INFO")
end
-- Initialize all registered components
InitRegistry:InitializeAll()
end
-- Expose registry to HealIQ
HealIQ.InitRegistry = InitRegistry
-- Safe initialization that works regardless of when this file loads
local success, error = pcall(performInitialization)
if not success then
if print then
print("|cFFFF0000HealIQ Init Error:|r " .. tostring(error))
end
end
-- Register for ADDON_LOADED event to ensure initialization happens
if not coreInitialized then
local initFrame = CreateFrame and CreateFrame("Frame") or nil
if initFrame then
initFrame:RegisterEvent("ADDON_LOADED")
initFrame:SetScript("OnEvent", function(self, event, loadedAddonName)
if loadedAddonName == "HealIQ" then
pcall(performInitialization)
initFrame:UnregisterEvent("ADDON_LOADED")
end
end)
end
end
-- Also try initialization on next frame if WoW API becomes available
if not coreInitialized and C_Timer and C_Timer.After then
C_Timer.After(0.1, function()
pcall(performInitialization)
end)
end