From AddOn Studio
Jump to navigation Jump to search

SecureStateDriver is a mechanism that allows secure handlers to register to be notified when conditions that are expressible using macro conditionals change. The handler can then respond by executing a snippet in the restricted environment, allowing (restricted) addon code to alter protected values while in combat.

The implementation is included as part of FrameXML in FrameXML/SecureStateDriver.lua. Conditionals are generally evaluated every 0.2 seconds, and in response to events guaranteed to alter some secure conditionals.


There are two functions provided by the Secure State Driver API: RegisterUnitWatch is the unit-frame special case, and RegisterStateDriver is the generic implementation.

RegisterStateDriver(frame, stateid, conditional)

Is the generic state driver -- you can register to be notified when an arbitrary macro conditional evaluates to a different values. Updates are delivered via attributes; handle OnAttributeChanged or use SecureHandlerStateTemplate with a corresponding snippet to respond from a restricted environment.
Frame-derived widget - notifications will be delivered to this frame.
String - an arbitrary identifier string for this conditional (coerced into lower case), or "visibility". The latter is a special state -- rather than delivering an update through attribute changes, it shows and hides the frame when the conditional evaluates to "show" or "hide" respectively.
String - macro conditional parsable by SecureCmdOptionParse. The value this conditional evaluates to will be set as the value of the "state-stateid" attribute on the frame.

RegisterUnitWatch(frame, asState)

Assists in controlling unit frames -- can either show/hide the frame based on whether its unit exists; or deliver that information via a state attribute.
Frame-derived widget - The frame to be shown/hidden/notified when its unit exists / does not exist.
Boolean - if true, the "state-unitexists" attribute will be set to a boolean value denoting whether the unit exists; if false, the frame will be shown if its unit exists, and hidden if it does not.


Showing/hiding a unit frame

local frame = CreateFrame("BUTTON", "MyParty1", UIParent, "SecureUnitButtonTemplate");
frame:SetAttribute("unit", "party1");
frame:SetWidth(50); frame:SetHeight(50); frame:SetPoint("CENTER");
local tex = frame:CreateTexture(); tex:SetAllPoints(); tex:SetTexture(1,0,0);

The snippet above will display a clickable unit frame for the "party1" unit (consisting solely of a red square in the center of your screen) only when one exists.

Responding to custom states

local frame = CreateFrame("FRAME", "MyStatefulFrame", UIParent, "SecureHandlerStateTemplate");
frame:SetAttribute("_onstate-petstate", [[ -- arguments: self, stateid, newstate
 if newstate == "nopet" then
  print("Where are you, kitty?");
 elseif newstate == "mypet" then
  print("Oh hai, kitty!");
 elseif newstate == "mcpet" then
  print("Curse your sudden but inevitable betrayal, kitty!"); -- Your pet is hostile to you.
RegisterStateDriver(frame, "petstate", "[target=pet,noexists] nopet;" ..
 " [target=pet,help] mypet; [target=pet,harm] mcpet");

The snippet above will print text to your chat frame when the state of your pet changes.