Quantcast
--[[
StarterLDB.lua
This is a simplistic example of a LDB (LibDataBroker) Addon.
It is assumed that you understand the Blizzard addon basics.
It is based loosely on the Titan Bag addon but is not Titan specific.

It is not required that a display addon exist for your addon to run; Such as Titan :-)
However your addon will need to enable command line commands or the user will not be able to see or do anything.

Enjoy!

By: The Titan Development Team
--]]

--[[ Folder Structure
NOTE: Before running this addon, the folder and file prefix must be the same to be considered for loading into WoW!
For example, to just run this as is, remove the 'Example' from the folder name then start or reload WoW.
This is explained in more detail below.


This plugin folder must be added to the Addon folder to be considered for loading into WoW.
Inside this folder you will notice :
- three .toc files
- one .lua file
- one .tga file.

There are sites (wowhead or wow wiki as examples) that have deeper explainations on addon development.
Please use these sites for more general addon information.

=== .toc
The folder and the .toc files MUST have the same name!
Sort of... the name prior to the underscore(_) must be the same. The name after that (postfix) has meaning to WoW.
WoW has three versions represented by the three postix values.
_Mainline : current retail version
_Wrath : Wrath of the Lich King version.
_Vanilla : Classic Era version
These values may change as the versions evolve, say Cata is added to Wrath.
Or they may not :). Years from now we may wonder why Wrath represents Dragonflight!

If your plugin is only for Classic Era then delete or rename the 'mainline' and 'wrath' .toc files.
Changing the filename will prevent WoW from loading the addon into that version of the game.

Titan uses this method. Notice Titan folder has no 'wrath' or 'vanilla' .toc.
TitanClassic has has both 'wrath' and 'vanilla' .toc but no 'mainline' .toc.
This allows Titan plugins intended for Classic versions to run without change.

NOTE: The ## Interface value should match the current interface value of the coorsponding WoW version.
In BattleNet this typcially shown below the 'Play' button.
DragonFlight 10.02.05 is represented without dots - 100205 - in the .toc.

If the interface value is close (but lower) WoW will complain that you are running 'older' addons.
If WoW finds a Classic Era value (say 11500) in a 'mainline' .toc, it will just ignore it (not load).
The reverse (a higher value) is true as well.

=== .lua
This is the code for the plugin - and this file.

=== .tga
This file is the icon used by the plugin.
It is specified in the .obj created for the LDB init routine.
WoW can use several different types of icons. This discussion is outside the scope of this example.

=== libs
This file implementing the LDB functions.
See https://github.com/tekkub/libdatabroker-1-1/wiki/ for an API description.
LibDataBroker-1.1.lua at https://github.com/tekkub/libdatabroker-1-1/
It *should* be included in the LDB compliant display addon.
It *should* included in the display addon.


Anyone can extract the code and art from WoW. This can be handy to get code examples.
And to grab icons to use for a plugin. My undestanding is any icon can be used within WoW without violating the ToS.
WoW icons tend to be .blp files. These files are NOT easy to look at or manipulate!!
You will need to research third party tools to manipulate .blp files.
--]]

-- ******************************** Constants *******************************
local ADDON_NAME = ...
-- Set the name we want in the global name space. Ensure the name is unique across all addons.
StarterLDB = {}

local id = "LDBStarter";  -- What the user will see as the name
local addon = ADDON_NAME  -- addon name / folder name / toc name

-- Localized strings are outside the scope of this example.

--[[
The artwork path must start with Interface\\AddOns
Then the name of the plugin
Then any additional folder(s) to your artwork / icons.
--]]
local artwork_path = "Interface\\AddOns\\TitanLDB\\"

--  Get data from the TOC file.
local version = tostring(GetAddOnMetadata(addon, "Version")) or "Unknown"
local author = GetAddOnMetadata(addon, "Author") or "Unknown"
-- NOTE: GetAddOnMetadata expects the addon name :
--       The addon folder name or .toc name needs to be the same.
-- ******************************** Variables *******************************
local trace = false -- toggle to show / hide debug statements in this addon

-- ******************************** Functions *******************************
local function Debug(debug_message, debug_type)
	if trace then
		local dtype = ""
		local time_stamp = ""
		local msg = ""
		if debug_type == "error" then
			dtype = "Error: "
		elseif debug_type == "warning" then
			dtype = "Warning: "
		end
		if debug_type == "normal" then
			time_stamp = ""
		else
			time_stamp = date("%H:%M:%S")..": "
		end

		msg =
			"Debug".." "
			..time_stamp
			..dtype
			..debug_message

		_G["DEFAULT_CHAT_FRAME"]:AddMessage(msg)
	else
		-- not requested
	end
	--date("%m/%d/%y %H:%M:%S")
end

-- Calculate bag space then return text and icon to display
local function GetBagSlotInfo()
	local totalSlots, usedSlots, availableSlots, icon
	totalSlots = 0;
	usedSlots = 0;
	for bag = 0, 4 do
		local size = C_Container.GetContainerNumSlots(bag);
		if (size and size > 0) then
			totalSlots = totalSlots + size;
			local free = C_Container.GetContainerNumFreeSlots(bag)
			local used = size - free
			usedSlots = usedSlots + used;
		end
	end
	availableSlots = totalSlots - usedSlots;

	local i,r = math.modf(availableSlots/2)
	if (r == 0) then
		icon = artwork_path.."Starter.tga"
	else
		icon = "Interface\\PetPaperDollFrame\\UI-PetHappiness" --PET_DISMISS_TEXTURE
	end

	local bagText
	bagText = format("%d/%d", availableSlots, totalSlots);

	bagText = HIGHLIGHT_FONT_COLOR_CODE..bagText..FONT_COLOR_CODE_CLOSE

	return bagText, icon
--]]
end

-- Create the tooltip
local function LDB_OnTooltipShow(tooltip)
	tooltip = tooltip or GameTooltip
	local tt_str = ""

	tt_str =
		GREEN_FONT_COLOR_CODE
		..id.." Info"
		..FONT_COLOR_CODE_CLOSE
	tooltip:AddLine(tt_str)

	local text, icon = GetBagSlotInfo()
	tt_str = "Available bag slots"
		.." "..text.."\n"
		.."\n".."Hint: Left-click to open all bags."

	tooltip:AddLine(tt_str)
end

local function LDB_Init(LDB_frame)
	Debug(id.." Init ...");
	--[[
	Initialize the Data Broker 'button'.
	This is the heart of a LDB plugin. It determines how the display addon is to treat this addon.

	Setting the type is required so the LDB lib and display addon know what to do. See the LDB spec.
	--]]
	-- The .obj is the key link to the display addon!!
	LDB_frame.obj =
		LibStub("LibDataBroker-1.1"):NewDataObject(id, {
			type = "data source", -- required
			-- SDK: The two options are:
			--      "data source" - A data source is expected to show some type of info
			--      "launcher" - Expected to open another window or perform some action

			-- For some unknown reason, Classic Era shows a tiny icon... Wrath and Retail show fine...
			icon = artwork_path.."Starter", -- The icon to display on the display addon
			label = id, -- label is the text the user will use to find this addon in the display addon.
			text  = "nyl", -- will be updated later
			OnTooltipShow = function(tooltip)
				LDB_OnTooltipShow(tooltip)
			end,
			OnClick = function(self, button)
				if ( button == "LeftButton" ) then
					-- Just a simple action to illustrate an LDB addon.
					ToggleAllBags();
				elseif ( button == "RightButton" ) then
					-- There is no action to take in this example.
					--[[ Add code here if your addon needs to do something on right click.
						Typically an options menu which is outside the scope of this example.
					--]]
				end
			end,
		})
	Debug(id.." Init fini.");
--]===]
end

-- Update the Bags Data Broker 'button'
local function LDB_Update(LDB_frame)
	local text, icon = GetBagSlotInfo()
	LDB_frame.obj.text = text
	LDB_frame.obj.icon = icon
end

-- Parse events registered to plugin and act on them
local function Button_OnEvent(self, event, ...)
	Debug("OnEvent"
		.." "..tostring(event)..""
		)
	if (event == "PLAYER_ENTERING_WORLD") then
		-- Do any additional set up needed
		--
		print(""
			.." "..tostring(id)..""
			.." "..tostring(version)..""
			.." by "..tostring(author)..""
			)

		-- Now that events have settled, register the one(s) we really want.
		-- This may not be needed but it could reduce churn and possible timing issues.
		self:RegisterEvent("BAG_UPDATE");

		-- Unregister events no longer needed.
		-- Good practice although this event is only fired on login
		self:UnregisterEvent("PLAYER_ENTERING_WORLD");
	end
	if event == "BAG_UPDATE" then
		LDB_Update(self)
	end
end

-- ====== Create needed frames
local function Create_Frames()
	-- general container frame
	-- The frame pointer is passed as a parameter rather than an addon local.
	local window = CreateFrame("Frame", "StarterLDBExample", UIParent)
--	window:Hide()

	-- Set strata as desired
	window:SetFrameStrata("FULLSCREEN")
	-- Using SetScript("OnLoad",   does not work

	window:SetScript("OnEvent", function(self, event, ...)
		Button_OnEvent(self, event, ...)
	end)

	-- Tell Blizzard this frame needs player entering world event.
	window:RegisterEvent("PLAYER_ENTERING_WORLD");

	-- Any other addon specific "on load" code here
	LDB_Init(window)
	-- Update the text (bag numbers)
	LDB_Update(window)

	-- shamelessly print a load message to chat window
	DEFAULT_CHAT_FRAME:AddMessage(
		GREEN_FONT_COLOR_CODE
		..addon..id.." "..version
		.." by "
		..FONT_COLOR_CODE_CLOSE
		.."|cFFFFFF00"..author..FONT_COLOR_CODE_CLOSE);
end

Create_Frames() -- do the work