-
Notifications
You must be signed in to change notification settings - Fork 0
Variables
Source package: com.jopre.streamlink.variable
A Variable is the runtime representation of a single named value that flows through
StreamLink's event → condition → action pipeline — things like event.user-name,
stream.hype-train-active, or a user-defined counter. Every Condition check, every
{{...}}/#...#-style placeholder substitution in an Action Item, and every persisted "global"
value is ultimately backed by an instance of com.jopre.streamlink.variable.Variable.
This page documents the variable package itself. See also:
-
Provider Variable Mapping — how
ProviderVariablebindings turn a provider's raw event payload intoVariableinstances, with each provider's own bindings on its own page: Provider: TWITCH, Provider: STREAM_LINK. -
Action Items — several items (
VariableStorageActionItem,VariableMathActionItem,VariableValueActionItem,VariablePersistenceActionItem) read/write Variables directly. -
Conditions —
VariableExistsCondition,StringCompareCondition, and the numeric/boolean conditions all evaluate against aVariable's value.
A Variable is never deserialized directly from a StreamLink config file the way an Action Item
or Condition is — instead it's constructed in code from one of a few source types, all keyed by
name into a shared Map<String, Variable> that's threaded through action/condition processing:
| Source type | Package | Turns into a Variable in... |
|---|---|---|
ProviderVariable |
com.jopre.streamlink.provider.variables |
ClientSideEventHandler.getVariables(...) — one Variable per matched field in the incoming Twitch/provider payload, scope PROVIDER
|
VariableDeclaration |
com.jopre.streamlink.action |
ActionProcessor.createActionVariables(...) — one Variable per Action-declared default, scope ACTION
|
| Hard-coded in event/system code | various | e.g. event.event-id (scope EVENT), stream.hype-train-active and the logged-in player name (scope SYSTEM) — see VariableScope below |
| Action Items that write variables | com.jopre.streamlink.action.type |
VariableStorageActionItem, VariableMathActionItem results, VariableValueActionItem copies |
Package: com.jopre.streamlink.variable · Implements Comparable<Variable>
| Field | Data Type | Description |
|---|---|---|
variableName |
String | The variable's key in the Map<String, Variable> it's stored in. |
scope |
VariableScope |
Where/how long the variable lives — see the enum section below. |
dataType |
VariableDataType |
Discriminator selecting which one of value/intVal/decimalVal/booleanVal actually holds the data. |
value |
String | Populated when dataType == STRING. |
intVal |
Integer | Populated when dataType == INTEGER. |
decimalVal |
Double | Populated when dataType == DECIMAL. |
booleanVal |
Boolean | Populated when dataType == BOOLEAN. |
dirty |
boolean | Set true by most constructors/setters to flag the variable as changed. Note: the (scope, name, value, dataType) constructor — the one used when parsing a stored string value, e.g. from VariableStorageActionItem — explicitly sets dirty = false instead, unlike every other constructor. Worth confirming whether that's intentional. |
valid |
boolean | Whether the variable currently holds a usable, correctly-typed value. Set true on a successful typed construction/set; the (scope, name, value, dataType) constructor sets it false if setTypedValue throws IllegalArgumentException (e.g. a non-numeric string handed to an INTEGER/DECIMAL variable) rather than propagating the error. |
| Constructor | Sets dataType to |
Notes |
|---|---|---|
Variable(VariableScope, String) |
(none) | Bare variable — dirty = true, no value/type set yet. |
Variable(VariableScope, String, Double) |
DECIMAL |
|
Variable(VariableScope, String, Integer) |
INTEGER |
|
Variable(VariableScope, String, Boolean) |
BOOLEAN |
|
Variable(VariableScope, String, String, VariableDataType) |
as given | Parses value via setTypedValue; the constructor most often used when hydrating a variable from a JSON/config/payload string (see setTypedValue below). Logs an error and sets valid = false on parse failure instead of throwing. |
Variable(Variable) |
copy of source | Copy constructor — copies every field including scope, dirty, and valid. |
-
setTypedValue(VariableDataType, String)/setTypedValue(String)— parses a raw string into the correct typed field for the givenVariableDataTypevia aswitch. ForSTRINGit's a plain assignment; forINTEGER/DECIMAL/BOOLEANit only parses when the input is non-blank (a blank input silently leaves the existing typed field untouched rather than clearing it). -
setValue(String)/setValue(Double)/setValue(Integer)/setValue(Boolean)— type-checked setters; each throwsIllegalArgumentExceptionif the variable'sdataTypedoesn't match the setter being called. Likely bug:setValue(Boolean)checksVariableDataType.INTEGER.equals(this.dataType)instead ofBOOLEAN— as written it rejects setting a boolean on aBOOLEAN-typed variable and would instead accept it on anINTEGER-typed one. -
setValue(Variable)— copies every field from anotherVariable(scope included). Used byVariableValueActionItemProcessorto copy one variable's value into another by reference. -
compareTo(Variable)and thecompareTo(Integer)/compareTo(Double)/compareTo(Boolean)/compareTo(String)overloads — back the numeric/string/boolean Condition checks.compareTo(Variable)throwsIllegalArgumentExceptionif either side is missing data, invalid, or the twodataTypes don't match. Likely bug: thecompareTo(String)overload builds a temporary STRING-typedVariablebut callstmpVar.setValue(booleanVal)(using the outer variable's own, almost always-nullbooleanValfield) instead ofsetValue(strVal)— as written, string comparisons through this overload look broken. (StringVariableConditionProcessor'sGREATERcase avoids this by callingcompareVar.getValue().compareTo(val)directly instead of going through this overload; its other branches —GREATER_OR_EQUAL,EQUAL,LESS_OR_EQUAL,LESS— do callcompareVar.compareTo(val), i.e. this overload.) -
toString()— returns the string form of whichever typed field is populated for the currentdataType. This is what backs placeholder substitution — see below. -
hasData()/validRequest(Variable)— private helpers backingcompareTo.
com.jopre.streamlink.action.processor.BaseProcessor.replacePlaceholders(String, Map<String, Variable>) is the method every Action Item processor runs message/text fields through (e.g.
ChatActionItem.chatMessage, ToastActionItem.title/message, CommandActionItem.commandName)
to substitute in variable values via Variable.toString().
Discrepancy worth flagging:
replacePlaceholdersonly recognizes tokens delimited by a single#on each side — e.g.#event.user-name#— via its hand-rolled scanner. It does not recognize the{{event.user-name}}-style Mustache placeholders used throughout this wiki's existing sample JSON (see Action Items). Either the sample JSON on this wiki predates a syntax change, or{{...}}is handled by some other code path not covered byBaseProcessor— worth confirming against actual runtime behavior before relying on either syntax. The#...#form is whatBaseProcessorimplements today.
Package: com.jopre.streamlink.variable · Used by: Variable.dataType, and (per
the Action Item Enums page)
VariableStorageActionItem.dataType.
| Constant | JSON Value | Description |
|---|---|---|
STRING |
string |
Value lives in Variable.value. |
INTEGER |
integer |
Value lives in Variable.intVal. |
DECIMAL |
decimal |
Value lives in Variable.decimalVal. |
BOOLEAN |
boolean |
Value lives in Variable.booleanVal. |
Package: com.jopre.streamlink.variable · Used by: Variable.scope, and (per the
Action Item Enums page)
VariableStorageActionItem.variableScope.
| Constant | JSON Value | Observed usage in current source |
|---|---|---|
PROVIDER |
provider |
Assigned by ClientSideEventHandler to every variable bound from an incoming provider payload via a ProviderVariable — e.g. all the TwitchVariableMap fields end up as PROVIDER-scoped variables at runtime. |
ACTION |
action |
The default scope: ActionProcessor.createActionVariables() uses it for Action-declared VariableDeclaration defaults, and it's also the fallback VariableStorageActionItem uses when its own variableScope field is omitted, plus the scope given to intermediate/result variables inside VariableMathActionItemProcessor. |
EVENT |
event |
Used specifically for the event.event-id variable that ClientSideEventHandler attaches to every fired event — not observed elsewhere in the reviewed source. |
GLOBAL |
global |
Special-cased by BaseProcessor.createOrUpdateVariable: a GLOBAL-scoped variable is stored in EventDataStore's process-wide globalVariables map instead of the per-event variable map, so it outlives any single event/action run. VariablePersistenceActionItem (variable-persistence) can additionally serialize every GLOBAL variable to/from stream-link-variables.json in the mod's config directory (StreamLinkConstants.VARIABLE_NAME_FILE), so this is also the only scope with disk persistence. |
SYSTEM |
system |
Used by StreamLink's own internal state, set directly in code rather than from a config file: the hype-train-active flag (StreamLinkConstants.HYPE_TRAIN_VAR_NAME, set/cleared in ClientSideEventHandler and StreamLinkClientMod) and the logged-in player name default (StreamLinkConstants.DEFAULT_USER_VARIABLE, set in StreamLinkClientMod). Both are stored via EventDataStore.setGlobalVariable(...), so — like GLOBAL — SYSTEM variables also live in the global variable map at runtime, just originating from mod code instead of a variable-storage action. |
Note:
GLOBALandSYSTEMboth end up inEventDataStore's global variable map at runtime — the enum constant only distinguishes where the variable came from (a config-drivenvariable-storageaction vs. StreamLink's own internal bookkeeping), not where it's stored.