Quantcast
Download
(1 Kb)
Download
Updated: 09-03-17 09:29 AM
Pictures
File Info
Compatibility:
Shadows of Argus (7.3.0)
Updated:09-03-17 09:29 AM
Created:09-03-17 09:29 AM
Downloads:39
Favorites:1
MD5:
7.3.0

Cerberus

Version: 1.1
by: Thex [More]

Description

Usually, when making an addon, you should put all your global functions and variable into one object specific to your addon, and this to avoid conflicts with other addons which could have global stuff with the same names as yours.
This is all well and good, but this has a few backdrops i'm not a fan of, for example, having to add yourObject.BeforeAnyFunctionDeclaration(), or self.beforeAnyVariableCall. Also, a mistake can easily slip through your fingers, if you forget to make a variable "local" when you intended it to be, etc.

So i made this tool to make it easier! It basically does all the work for you.
Cerberus will "catch" everything you don't declare as local, and stores it in a table specific to your addon. And whenever trying to access a global variable or function, it will check if it is in the said table, and return it to you, or return it from _G if it doesn't have it (_G being, if you don't know, the table on which all global stuff is stored).
So with this tool, you don't have to bother, just put all your intended-to-be globals as globals, and let Cerberus nest them for you!


How to use

The tool is pretty much a "setup and forget", however it does require some initializations, as well as at least some understanding of what it's doing, if you want to be able to use it properly. (Don't worry though, it's very simple and short)

First of all, you should put Cerberus.lua before any of your files in your toc file; but under any other library file.
Example:



Then, in the first file loaded afterwards (in the example above, that would be Options.lua), you need to add the following line at the very top of the file:

g_cerberus.RegisterAddon("YourAddonName");

Normally, your addon name should be enough, but if it's a very generic one, you might want to give a more specific one there, to avoid potential conflicts (it doesn't have to be identical to your actual addon name, it's just a name for Cerberus to identify your addon).
And after that's done, you will need to put the following line a the very top of every one of your other files (not in the one where you added the previous line!):

Cerberus_HookThisFile();

(Please note that this second function does not go through the g_cerberus object, it is a global function; i wish i could have made them work both the same way but because of how it works, it simply isn't possible).
The two lines above mentioned should be put in the global scope, and Cerberus will not work if you add them in a function or anything else. If you want to have some global variables specifically meant to be declared on _G, then you can put them before the Cerberus_HookThisFile() call, but i believe it is better practice to use "_G["YourGlobalVariableName"] = whatever;" instead, as this clearly states your intentions .

If your addon uses saved variables, you will have to "declare" them to Cerberus, by giving a table containing all their names to the RegisterAddon() function, like so:

g_cerberus.RegisterAddon("YourAddonName", { "SavedVariable1", "SavedVariable2", "Etc" } );

This will tell Cerberus to use these variables as normal global ones (it will not add them to your addon's Cerberus table, always go directly through _G), so they will be saved and loaded correctly. The names of the variables passed must correspond exactly to the ones in your toc file. Please keep in mind that the names of the saved variables should still be specific enough to avoid conflicts with other mods.
If you use a library or tool that handles your saved variables in a different way than "normal", i have no idea how to handle that case, because i don't use any, so you might want to try and figure out how to do it yourself (and i would appreciate your input, in order to improve Cerberus for those cases).

If you have an addon which behaves as an optional module to a core one, and you would like it to use the same global space as said core addon, you can use the following line in your module, where you would normally use RegisterAddon(), but instead of g_cerberus.RegisterAddon()!

g_cerberus.RegisterAddonModule("YourCoreAddonName", { "SavedVariable3" });

(The name given as parameter here must then be the same as the one used with RegisterAddon() in the core addon)
You won't need to reregister the core addon's saved variables, but if your module has some saved variables of its own, you can add them here the same way as you would have with RegisterAddon().

If for some reason you wish to access your addon's Cerberus global table, the same way you would access _G, you can do so this way:

cerberus_G["VarOfFuncName"];
(Just like you would use _G but with cerberus_G instead).


How it works

This tool uses the lua function setfenv() whenever you use Cerberus_HookThisFile() in a file, in order to change the environment of that file from _G to a table contained in the global object g_cerberus. This means that for N addons using Cerberus, only one global object (g_cerberus) would be created, and inside this object, there would be N tables used by each addon. All addons can have functions and variables with the same name but there would still be different versions used only by the appropriate addon.
Also, whenever you access a variable or function that hasn't been created by yourself (stored on _G, like function print() or whatever), it tries to find it in cerberus_G, and if it's not found, it is copied inside cerberus_G, to avoid indirection on often used functions and variables.

All this means that if you don't specifically use "_G["Something"] = something;", nothing will ever be written on _G. Everything you write on the global scope will be stored in your Cerberus table and preferred over _G. This allows you to safely hook blizzard's functions and variables too. The hook will only be used by your addon (and its modules) and noone else (this does not include functions stored as members of elements such as frames).
This also means, however, that if you want to add slash commands, for example, then, where you'd normally declare a global "SLASH_MYADDON1 = "/myAddon"", now you will need to do it directly through _G, like so: "_G["SLASH_MYADDON1"] = "/myAddon"".
In a similar fashion, that's what Cerberus automatically does whenever you use your saved variables (if you registered them).
(Please note, if you're not familiar with _G, that whenever trying to access, say, the variable named myGlobalVariable, you have to put it into quoting marks "" : _G["myGlobalVariable"]; Same thing when trying to access variables from your Cerberus table: cerberus_G["myGlobalVariable"]; ).


Incompatibilities

I do not believe it is fully compatible with AceHook. I would be interested in making a compatibility patch or something, but i never used it myself, and i failed to entirely grasp how it works when looking into it.
Therefore, if you happen to be using AceHook, i would be interested in talking with you about what you use it for and how, see what could be done for that compatibility patch.


Disclaimer

This tool has been intended to be kept simple and small. I made it work with what i use it for, and it wouldn't surprise me if it wasn't that helpful with very advanced and complicated cases. I simply don't have enough experience with very huge, complicated and intricate addons to tell if it would work 100% in every case, but i think it should; the only thing that i know might vary is how useful it might be to your specific case.
If you have any issue while using this, or have any question, remark or suggestion, please don't hesitate to contact me or post them directly in the comments!

Optional Files (0)


There have been no comments posted to this file.
Be the first to add one.



Category Jump: