Hi All,
I asked the question "What is LibStub?" in the wrong forum on accident. Since I asked that question, I went and did some research and actually figured it out myself.
I'd like to post here my findings/conclusions so that it may help other people who have the same question I did. If you see anything wrong here, please feel free to correct me.
The following block of code is the exact code of LibStub.lua with detailed explanations of everything that is happening. I use the addon "LibAddonMenu-1.0" as an example throughout these explanations...thanks to Seerah for unknowingly allowing me to use his addon as an example
Lua Code:
-- LibStub is a simple "version control" stub of code that ensures you are using the latest
-- version of all libraries that are registered with it...including itself.
-- Example: Your ESO client is running 2 different add-ons and both of them use the
-- library "LibAddonMenu-1.0". However, one of the add-ons uses minor version 2
-- and the other minor version 4. LibStub will ensure that the latest version
-- (version 4) is used by both add-ons.
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 1
-- the _G table is the Lua "environment" where all Global variables are stored.
-- The point of this statement is to see if "LibStub" already exists in memory,
-- or more specifically, was already loaded by another add-on unknown to your add-on.
-- If LibStub has not been loaded yet anywhere, _G[LIBSTUB_MAJOR] will return nil.
local LibStub = _G[LIBSTUB_MAJOR]
local strformat = string.format
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
--[[
If you got here, either LibStub was undefined (nil) or the current LibStub in memory has a lesser
minor revision number than this one. Assuming LibStub was undefined since this is version 1,
the following 3 lines create a table titled 'LibStub' which looks like:
LibStub = {
libs = {}
minors = {}
minor = 1
}
and sets the global variable "LibStub" equal to this table. This global table is now the LibStub definition
for ALL add-ons that use it.
If a newer version of LibStub exists in an add-on somewhere, that version will get used instead since the global
table "LibStub" will be set there.
--]]
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
-- Register a new library with LibStub
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
minor = assert(tonumber(zo_strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
-- Example: major = "LibAddonMenu-1.0" and minor = 4
-- oldminor = LibStub.minors["LibAddonMenu-1.0"]
-- If a version of LibAddonMenu is already loaded into memory, oldminor will contain it's version number.
-- Otherwise, oldminor = nil.
local oldminor = self.minors[major]
-- If a version of LibAddonMenu is already in memory AND it's version number is greater than or equal to
-- the new library, exit the function and return nil.
if oldminor and oldminor >= minor then return nil end
-- If you got here, that means either this new library doesn't exist in memory or it's a newer version
-- Set the minor version number of LibAddonMenu to 4. If LibStud.libs["LibAddonMenu-1.0"] already exists,
-- continue to use that library. Otherwise, set to {}.
-- LibStub.minors["LibAddonMenu-1.0"] = 4, LibStub.libs["LibAddonMenu-1.0"] = LibStub.libs["LibAddonMenu-1.0"] or {}
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
-- Return the library table and the oldminor version number.
-- If this is a brand new library (not in memory already) the library table will be empty.
return self.libs[major], oldminor
end
-- Grabs a library for you to use. For example, if you want to use the LibAddonMenu-1.0 library
-- you would call LAM = LibStub:GetLibrary("LibAddonMenu-1.0"). This returns all definitions
-- of the library (methods, variables, tables, etc.) into your new object LAM.
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(("Cannot find a library instance of %q."):strformat(tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
-- See all libraries currently registered with LibStub in memory
function LibStub:IterateLibraries() return pairs(self.libs) end
-- Allows a shortcut way to call the GetLibrary function.
-- These two calls become 100% equivalent:
-- LAM = LibStub:GetLibrary("LibAddonMenu-1.0")
-- LAM = LibStub("LibAddonMenu-1.0")
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
If you have any questions please feel free to ask!