view DependencyLoader/Addon.lua @ 18:e7995d599184 tip

updated pkgmeta fix the inversion in addon:Enable added support for late-loading
author mckenziemc
date Tue, 21 Dec 2010 00:23:57 -0800
parents f825ccf94a89
children
line wrap: on
line source
--	Addon
--	Represents individual addon modules.


local addonName, addonTable = ...


local debug = addonTable.debug

--	TODO: test if the API functions are quicker with indexes than names.
--	TODO: modify the dependency stuff to check the Errata module.

local Addon, addon = addonTable:NewClass("Addon")

Addon.addons = {}
Addon.nameToIndex = {}


---	(private) Creates a new Addon object
--	@param	id		Name or index of the addon.
function Addon:New(id)
	local instance = {}
	setmetatable(instance, self.instanceMetatable)
	
	if type(id) == "number" then
		--	TODO: make sure it's in range
		instance.index = id
		instance.name = GetAddOnInfo(id)
	else
		--	FIXME: allow blizzard addons?
		local index
		
		for i=1,GetNumAddOns() do
			if GetAddOnInfo(i) == id then
				index = i
				break
			end
		end
		
		if index then
			instance.name = GetAddOnInfo(id)
			instance.index = index
		else
			local message = "Addon not found: "..(id or "nil")
			error(message)
		end
	end
	
	return instance
end


---	Retrieves an Addon object.
--	@param	id	Name or index of the addon to retrieve.
--	@return 	The Addon object, or nil if not found.
function Addon:Get(id)
	assert(id)
	
	if not self:Exists(id) then
		return nil
	end
	
	if type(id) == "number" then
		if self.addons[id] ~= nil then
			return self.addons[id]
		end
		
		local new = self:New(id)
		self.addons[new:GetIndex()] = new
		self.nameToIndex[new:GetName()] = id
		
		return new
	elseif type(id) == "string" then
		if self.nameToIndex[id] then
			return self.addons[self.nameToIndex[id] ]
		end
		
		local new = self:New(id)
		self.addons[new:GetIndex()] = new
		self.nameToIndex[id] = new:GetIndex()
		
		return new
	end
end	


--	Checks if an addon exists with the specified name.
--	@param	addon	Name of the addon.
--	@return			True if the addon is present, false otherwise.
function Addon:Exists(addon)
	if type(addon) == "number" then
		if addon >= 1 and addon <= GetNumAddOns() then
			return true
		else
			return false
		end
	elseif type(addon) == "string" then
		if addon:match("Blizzard_") then
			return false
		end
		
		local status = select(6, GetAddOnInfo(addon))
		
		if status == "MISSING" then
			return false
		else
			return true
		end
	else
		local message = string.format("Unexpected argument type: \"%s\", value: %s", type(addon), addon or "nil")
		error(message)
	end
end


function addon:GetName()
	return self.name
end


function addon:GetIndex()
	return self.index
end


function addon:IsEnabled()
	--	FIXME: written while tired; review later
	local status = select(6, GetAddOnInfo(self.index))
	
	if status == "DISABLED"	then
		return false
	else
		return true
	end
end


function addon:IsLoaded()
	if IsAddOnLoaded(self.index) then
		return true
	else
		return false
	end
end


---	Checks if the addon is loadable.
--	Considers interface issues, missing, etc. (NYI)
--	Does not check dependencies.
function addon:CanLoad()
	--	FIXME: an addon may be present but unloadable if loading out of date addons is disabled.
	return true
end


function addon:CanLoD()
	--	FIXME: what will the client say about addons using LoadManagers if the LM was force-loaded?
	if IsAddOnLoadOnDemand(self.name) then
		return true
	else
		return false
	end
end


function addon:CanLoadLate()
	--	TODO: check Errata module
	return false
end


--	can this addon be force-loaded after the point where the client would enable it?
function addon:CanForceLoadAfter()
	--	TODO: check Errata module
	return false
end


--	can this addon be force-loaded before the point where the client would enable it?
function addon:CanForceLoadBefore()
	--	TODO: check Errata module
	return false		--	TODO: check if there's any reason addons can't be forceloaded
end


function addon:CanForceLoad()
	--	FIXME: check if this would've already been loaded
	return self:CanForceLoadAfter() or self:CanLoD()
	--	FIXME: should CanLoD() be in here?
end


function addon:Enable()
	if IsLoggedIn() then
		addonTable.classes.Core:RawEnableAddOn(self.name)
	else
		addonTable.classes.Core:QueueEnable(self.name)
	end
end


--	NOTE: only call for LoD, not force-loading
function addon:Load()
	assert(self:CanLoD())
	
	addonTable.classes.Core:RawEnableAddOn(self.name)
	addonTable.classes.Core:RawLoadAddOn(self.name)
end


function addon:LoadLate()
	classes.Core:RawEnableAddOn(self.name)
	classes.Core:RawLoadAddOn(self.name)
end


function addon:ForceLoad()
	debug("addon:ForceLoad called on", self.name)

	assert(self:CanForceLoad())
	--	TODO: make sure force-loading is available at this time
	
	addonTable.Core:RawEnableAddOn(self.name)	--	This should cause the game to also load this addon
end


function addon:GetDependencies()
	--	TODO: consider no-lib embeds as deps?
	return GetAddOnDependencies(self.index)
end


function addon:GetEmbeds()
	local embeds = {}
	
	local embedString = GetAddOnMetadata(self.name, "X-Embeds")
	
	if embedString then
		for match in string.gmatch(embedString, "[^,%s]+") do
			table.insert(embeds, match)
		end
	end
	
	return unpack(embeds)
end