431 lines
16 KiB
Lua
431 lines
16 KiB
Lua
--[[
|
|
This file is part of Decursive.
|
|
|
|
Decursive (v 2.5.1-6-gd3885c5) add-on for World of Warcraft UI
|
|
Copyright (C) 2006-2007-2008-2009 John Wellesz (archarodim AT teaser.fr) ( http://www.2072productions.com/to/decursive.php )
|
|
|
|
Starting from 2009-10-31 and until said otherwise by its author, Decursive
|
|
is no longer free software, all rights are reserved to its author (John Wellesz).
|
|
|
|
The only official and allowed distribution means are www.2072productions.com, www.wowace.com and curse.com.
|
|
To distribute Decursive through other means a special authorization is required.
|
|
|
|
|
|
Decursive is inspired from the original "Decursive v1.9.4" by Quu.
|
|
The original "Decursive 1.9.4" is in public domain ( www.quutar.com )
|
|
|
|
Decursive is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
--]]
|
|
-------------------------------------------------------------------------------
|
|
|
|
|
|
local addonName, T = ...;
|
|
DecursiveRootTable = T;
|
|
|
|
DecursiveInstallCorrupted = false;
|
|
|
|
DcrC = {}; -- needed until we get rid of the xml based UI.
|
|
T._C = DcrC;
|
|
local DC = DcrC;
|
|
|
|
DC.StartTime = GetTime();
|
|
DC.MyClass = "unknown";
|
|
|
|
T._LoadedFiles = {
|
|
["Dcr_DIAG.xml"] = false,
|
|
["Dcr_DIAG.lua"] = false,
|
|
["DCR_init.lua"] = false,
|
|
["Dcr_LDB.lua"] = false,
|
|
["Dcr_utils.lua"] = false,
|
|
|
|
["enUS.lua"] = false,
|
|
["frFR.lua"] = false,
|
|
["deDE.lua"] = false,
|
|
["zhTW.lua"] = false,
|
|
["esES.lua"] = false,
|
|
["koKR.lua"] = false,
|
|
["zhCN.lua"] = false,
|
|
["ruRU.lua"] = false,
|
|
|
|
["Dcr_opt.lua"] = false,
|
|
["Dcr_Events.lua"] = false,
|
|
["Dcr_Raid.lua"] = false,
|
|
["Decursive.lua"] = false,
|
|
["Dcr_lists.lua"] = false,
|
|
["Dcr_DebuffsFrame.lua"] = false,
|
|
["Dcr_LiveList.lua"] = false,
|
|
|
|
["Dcr_DebuffsFrame.xml"] = false,
|
|
["Dcr_lists.xml"] = false,
|
|
["Dcr_LiveList.xml"] = false,
|
|
["Decursive.xml"] = false,
|
|
|
|
};
|
|
|
|
-- This self diagnostic functionality is here to give clear instructions to the
|
|
-- user when something goes wrong with the Ace shared libraries or when a
|
|
-- Decursive file could not be loaded.
|
|
|
|
-- the beautiful error popup : {{{ -
|
|
StaticPopupDialogs["DECURSIVE_ERROR_FRAME"] = {
|
|
text = "|cFFFF0000Decursive Error:|r\n%s",
|
|
button1 = "OK",
|
|
OnAccept = function()
|
|
return false;
|
|
end,
|
|
timeout = 0,
|
|
whileDead = 1,
|
|
hideOnEscape = false,
|
|
showAlert = 1,
|
|
}; -- }}}
|
|
T._FatalError = function (TheError) StaticPopup_Show ("DECURSIVE_ERROR_FRAME", TheError); end
|
|
|
|
-- Decursive LUA error manager and debug reporting functions {{{
|
|
|
|
local function NiceTime()
|
|
return tonumber(("%.4f"):format(GetTime() - DC.StartTime));
|
|
end
|
|
|
|
local function print(t)
|
|
if DEFAULT_CHAT_FRAME then
|
|
DEFAULT_CHAT_FRAME:AddMessage(t);
|
|
end
|
|
end
|
|
|
|
-- taken from AceConsole-2.0
|
|
local function tostring_args(a1, ...)
|
|
if select('#', ...) < 1 then
|
|
return tostring(a1)
|
|
end
|
|
return tostring(a1), tostring_args(...)
|
|
end
|
|
|
|
T._DebugText = "";
|
|
-- inspired from BugSack
|
|
function T._DebugFrameOnTextChanged(frame)
|
|
if frame:GetText() ~= T._DebugText then
|
|
frame:SetText(T._DebugText)
|
|
end
|
|
frame:GetParent():UpdateScrollChildRect()
|
|
local _, m = DecursiveDebuggingFrameScrollScrollBar:GetMinMaxValues()
|
|
if m > 0 and frame.max ~= m then
|
|
frame.max = m
|
|
DecursiveDebuggingFrameScrollScrollBar:SetValue(0)
|
|
end
|
|
end
|
|
|
|
T._DebugTextTable = {};
|
|
local DebugTextTable = T._DebugTextTable;
|
|
local Reported = {};
|
|
local GetFramerate = _G.GetFramerate;
|
|
local GetNetStats = _G.GetNetStats;
|
|
function T._AddDebugText(a1, ...)
|
|
|
|
if T.Dcr.Debug then
|
|
T.Dcr:Debug("Error processed");
|
|
end
|
|
local text = "";
|
|
|
|
if select('#', ...) > 0 then
|
|
text = strjoin(", ", tostring_args(a1, ...))
|
|
else
|
|
text = tostring(a1);
|
|
end
|
|
|
|
if not Reported[text] then
|
|
table.insert (DebugTextTable, ("\n------\n%.4f (%d-%d): %s -|count: "):format(NiceTime(), select(3, GetNetStats()), GetFramerate(), text) );
|
|
table.insert (DebugTextTable, 1);
|
|
Reported[text] = #DebugTextTable;
|
|
else
|
|
DebugTextTable[Reported[text]] = DebugTextTable[Reported[text]] + 1;
|
|
end
|
|
end
|
|
|
|
local AddDebugText = T._AddDebugText;
|
|
|
|
-- The error handler
|
|
local ProperErrorHandler = false;
|
|
local IsReporting = false;
|
|
|
|
local version, build, date, tocversion = GetBuildInfo();
|
|
|
|
T._CatchAllErrors = false;
|
|
T._tocversion = tocversion;
|
|
|
|
function T._DecursiveErrorHandler(err, ...)
|
|
|
|
-- second blizzard bug HotFix
|
|
---[=[
|
|
if ScriptErrorsFrameScrollFrameText then
|
|
if not ScriptErrorsFrameScrollFrameText.cursorOffset then
|
|
ScriptErrorsFrameScrollFrameText.cursorOffset = 0;
|
|
if ( GetCVarBool("scriptErrors") ) then
|
|
print("Decursive |cFF00FF00HotFix to Blizzard_DebugTools:|r |cFFFF0000ScriptErrorsFrameScrollFrameText.cursorOffset was nil (check for Lua errors using BugGrabber and BugSack)|r");
|
|
end
|
|
end
|
|
end
|
|
--]=]
|
|
|
|
err = tostring(err);
|
|
|
|
--Add a check to see if the error is happening inside the Blizzard debug tool himself...
|
|
if (err:lower()):find("blizzard_debugtools") then
|
|
if ( GetCVarBool("scriptErrors") ) then
|
|
print (("|cFFFF0000%s|r"):format(err));
|
|
end
|
|
return;
|
|
end
|
|
|
|
if not IsReporting and (T._CatchAllErrors or (err:lower()):find("decursive") and not (err:lower()):find("\\libs\\")) then
|
|
T._CatchAllErrors = false; -- Errors are unacceptable so one is enough, no need to get all subsequent errors.
|
|
IsReporting = true;
|
|
AddDebugText(err, debugstack(2), ...);
|
|
if T.Dcr then
|
|
T.Dcr:Debug("Error recorded");
|
|
end
|
|
IsReporting = false;
|
|
end
|
|
|
|
if ProperErrorHandler then
|
|
return ProperErrorHandler( err, ... ); -- returning this way prevents this function from appearing in the stack
|
|
end
|
|
end
|
|
|
|
function T._HookErrorHandler()
|
|
if not ProperErrorHandler then
|
|
|
|
---[=[
|
|
-- seems to be required even in 3.3 because debuglocals, unlike debugstack is sensitive to intermediates so we need to add 1 to its level for each intermediate
|
|
if GetCVarBool("scriptErrors") and not BugGrabber then
|
|
-- this whole block is a bad idea, it could create cascading tainting issues if an error occur in a Blizz secured code...
|
|
-- it is enabled only if the user turned Lua error reporting on otherwise no one cares about debuglocals being useless.
|
|
T._original_debuglocals = _G.debuglocals;
|
|
_G.debuglocals = function (level)
|
|
local ADDLEVEL = 2; -- 2 is for this function and _DecursiveErrorHandler
|
|
|
|
-- test for other add-on that hooks the error handler and increment ADDLEVEL
|
|
if QuestHelper_Errors then
|
|
ADDLEVEL = ADDLEVEL + 1;
|
|
end
|
|
|
|
if Swatter and Swatter.OnError then
|
|
ADDLEVEL = ADDLEVEL + 1;
|
|
end
|
|
|
|
|
|
return T._original_debuglocals(level + ADDLEVEL) or "Sometimes debuglocals() returns nothing, it's one of those times... (FYI: This last sentence (only) is a HotFix from Decursive to prevent a C stack overflow in the new Blizzard error handler and thus giving you the opportunity to send this debug report to the author of the problematic add-on so he/she can fix it)";
|
|
end;
|
|
end
|
|
--]=]
|
|
|
|
|
|
ProperErrorHandler = geterrorhandler();
|
|
seterrorhandler(T._DecursiveErrorHandler);
|
|
end
|
|
end
|
|
|
|
--}}}
|
|
|
|
|
|
-- Dev version usage warning {{{
|
|
-- the beautiful beta notice popup : {{{ -
|
|
StaticPopupDialogs["Decursive_Notice_Frame"] = {
|
|
text = "|cFFFF0000Decursive Notice:|r\n%s",
|
|
button1 = "OK",
|
|
OnAccept = function()
|
|
return false;
|
|
end,
|
|
timeout = 0,
|
|
whileDead = 1,
|
|
hideOnEscape = false,
|
|
showAlert = 1,
|
|
}; -- }}}
|
|
|
|
|
|
|
|
-- }}}
|
|
|
|
do
|
|
T._DiagStatus = false;
|
|
|
|
local PrintMessage = function (message, ...) if T._DiagStatus ~= 2 then T.Dcr:Print("|cFFFFAA55Self diagnostic:|r ", format(message, ...)); end end;
|
|
|
|
-- {{{
|
|
function T._SelfDiagnostic (force, FromCommand)
|
|
|
|
-- will not executes several times unless forced
|
|
if not force and T._DiagStatus then
|
|
return T._DiagStatus;
|
|
end
|
|
|
|
T._DiagStatus = 0; -- will be set to 1 if the diagnostic fails
|
|
|
|
-- Table with all the required libraries with their current revision at Decursive release time.
|
|
|
|
--LibStub:GetLibrary
|
|
local UseLibStub = {
|
|
["AceAddon-3.0"] = 5,
|
|
["AceConsole-3.0"] = 7,
|
|
["AceEvent-3.0"] = 3,
|
|
["AceTimer-3.0"] = 5,
|
|
["AceHook-3.0"] = 5,
|
|
["AceDB-3.0"] = 21,
|
|
["AceDBOptions-3.0"] = 12,
|
|
["AceLocale-3.0"] = 2,
|
|
["AceComm-3.0"] = 6,
|
|
|
|
["AceGUI-3.0"] = 33,
|
|
["AceConfig-3.0"] = 2,
|
|
["AceConfigRegistry-3.0"] = 12,
|
|
["AceConfigCmd-3.0"] = 12,
|
|
["AceConfigDialog-3.0"] = 49,
|
|
|
|
["LibDataBroker-1.1"] = 4,
|
|
["LibDBIcon-1.0"] = 14,
|
|
["LibQTip-1.0"] = 34,
|
|
["CallbackHandler-1.0"] = 5,
|
|
};
|
|
|
|
local GenericErrorMessage1 = "Decursive could not initialize properly because one or several of the required shared libraries (at least |cFF00FF00AceLibrary or LibStub|r) could not be found.\n";
|
|
local GenericErrorMessage2 = "Try to re-install Decursive from its original archive or use the |cFF00FF00Curse client|r (Curse.com) to update |cFFFF0000ALL|r your add-ons properly.";
|
|
|
|
local ErrorFound = false;
|
|
local Errors = {};
|
|
local FatalOccured = false;
|
|
|
|
-- Check each version of the required libraries that use LibStub
|
|
if LibStub then
|
|
for k,v in pairs(UseLibStub) do
|
|
if LibStub:GetLibrary(k, true) then
|
|
if (select(2, LibStub:GetLibrary(k))) < v then
|
|
table.insert(Errors, ("The shared library |cFF00FF00%s|r is out-dated, revision |cFF0077FF%s|r at least is required.\n"):format(k, tostring(v)));
|
|
end
|
|
else
|
|
table.insert(Errors, ("The shared library |cFF00FF00%s|r could not be found!!!\n"):format(k));
|
|
FatalOccured = true;
|
|
end
|
|
end
|
|
else
|
|
table.insert(Errors, GenericErrorMessage1);
|
|
FatalOccured = true;
|
|
end
|
|
|
|
|
|
-- check if all Decursive files are loaded
|
|
local mixedFileVersionsdetection = {};
|
|
local MixedVersionsCount = 0;
|
|
if not FatalOccured then
|
|
for k,v in pairs (T._LoadedFiles) do
|
|
if v and v ~= "@pro" .. "ject-version@" and not mixedFileVersionsdetection[v] then
|
|
mixedFileVersionsdetection[v] = k;
|
|
MixedVersionsCount = MixedVersionsCount + 1;
|
|
end
|
|
|
|
if not v then
|
|
table.insert(Errors, ("The Decursive file |cFF00FF00%s|r could not be loaded!\n"):format(k));
|
|
FatalOccured = true;
|
|
end
|
|
end
|
|
end
|
|
|
|
if MixedVersionsCount > 1 then
|
|
-- some mixed files were detected
|
|
local MixedDetails = "|cFFFF5599The versions of these files differ|r:\n\n";
|
|
for k,v in pairs (mixedFileVersionsdetection) do
|
|
MixedDetails = ("%s%s --> %s\n"):format(MixedDetails, v, k);
|
|
end
|
|
|
|
table.insert(Errors, ("Decursive installation is corrupted, mixed versions detected!\n\n%s\n"):format(MixedDetails));
|
|
FatalOccured = true;
|
|
end
|
|
|
|
if #Errors > 0 then
|
|
local ErrorString = ("|cFFFF0000%d error(s)|r found while loading Decursive:\n\n"):format(#Errors);
|
|
|
|
for k, v in pairs (Errors) do
|
|
ErrorString = ErrorString .. v;
|
|
end
|
|
|
|
ErrorString = ErrorString .. "\n\n" .. GenericErrorMessage2;
|
|
|
|
T._FatalError(ErrorString);
|
|
T._DiagStatus = FatalOccured and 2 or 1;
|
|
end
|
|
|
|
-- if the diagnostic was requested by the user, we also test AceEvent functionalities {{{ -
|
|
if force and FromCommand and T._DiagStatus == 0 then
|
|
|
|
PrintMessage("|cFF00FF00No problem found in shared libraries or Decursive files!|r");
|
|
|
|
PrintMessage("Now checking spell translations...");
|
|
if T.Dcr:GetSpellsTranslations(true) then
|
|
PrintMessage("|cFF00FF00No error found in spell translations!|r");
|
|
end
|
|
|
|
AddDebugText("Now checking the event management library...");
|
|
PrintMessage("Now checking the event management library...");
|
|
PrintMessage("If, in about 2 seconds, the message \"|cFF00FF00Event library functionning properly|r\" does not appear then there is a problem");
|
|
|
|
local OneTimeEvent = "not set"; local ReapeatingEventRate = 1; local ReapeatingEventCount = 0; local CustomEvent = "DCR_TEST_DIAG_EVENT"; local CustomEventCaught = "not set";
|
|
local ConfirmOneTimeEventMessage = "That was a good time!";
|
|
local ConfirmCustomEventMessage = "I was really caught!";
|
|
|
|
-- Register a curstom event
|
|
T.Dcr:RegisterMessage(CustomEvent, function(message, DiagTestArg1) CustomEventCaught = DiagTestArg1; T.Dcr:Debug("CustomEvent callback executed"); end);
|
|
|
|
-- Schedule a function call in 0.5s
|
|
T.Dcr:ScheduleDelayedCall("DcrDiagOneTimeEvent", function(DiagTestArg2) OneTimeEvent = DiagTestArg2; T.Dcr:Debug("OneTimeEvent callback executed"); end, ReapeatingEventRate / 2, ConfirmOneTimeEventMessage);
|
|
|
|
-- Set a repeating function call that will check for other test event completion
|
|
T.Dcr:ScheduleRepeatedCall("DcrDiagRepeat",
|
|
function (argTest)
|
|
local argtestdone = false;
|
|
if not argtestdone and argTest ~= "test" then
|
|
AddDebugText("Event lib management error: argument could not be read!");
|
|
PrintMessage("|cFFFF0000Event lib management error: argument could not be read!|r");
|
|
argtestdone = true;
|
|
end
|
|
|
|
if OneTimeEvent == ConfirmOneTimeEventMessage and CustomEventCaught == ConfirmCustomEventMessage then
|
|
T.Dcr:CancelDelayedCall("DcrDiagRepeat");
|
|
T.Dcr:UnregisterMessage(CustomEvent);
|
|
PrintMessage("|cFF00FF00Event library functionning properly!|r");
|
|
PrintMessage("|cFF00FF00Everything seems to be OK.|r");
|
|
AddDebugText("Event library functionning properly, Everything seems to be OK");
|
|
return;
|
|
else
|
|
T.Dcr:Debug(OneTimeEvent, "is not", ConfirmOneTimeEventMessage, "and", CustomEventCaught, "is not", ConfirmCustomEventMessage);
|
|
end
|
|
|
|
-- cast the custom event
|
|
T.Dcr:SendMessage(CustomEvent, ConfirmCustomEventMessage);
|
|
|
|
if ReapeatingEventCount == 4 then
|
|
AddDebugText("A problem occured, OneTimeEvent:", OneTimeEvent, "CustomEventCaught:", CustomEventCaught);
|
|
PrintMessage("|cFFFF0000A problem occured, OneTimeEvent='%q', CustomEventCaught='%q'|r", OneTimeEvent, CustomEventCaught);
|
|
T.Dcr:CancelDelayedCall("DcrDiagRepeat");
|
|
T.Dcr:UnregisterMessage(CustomEvent);
|
|
return;
|
|
end
|
|
|
|
ReapeatingEventCount = ReapeatingEventCount + 1;
|
|
|
|
end,
|
|
ReapeatingEventRate, "test");
|
|
|
|
end -- }}}
|
|
|
|
if T._DiagStatus == 0 then
|
|
DecursiveInstallCorrupted = nil;
|
|
end
|
|
|
|
return T._DiagStatus;
|
|
|
|
|
|
end -- }}}
|
|
end
|
|
|
|
|
|
T._LoadedFiles["Dcr_DIAG.lua"] = "2.5.1-6-gd3885c5";
|