Problem/Opportunity Space
Currently alias command sequences are completely static - the same commands fire every time regardless of how the alias is invoked. There is no way to pass dynamic input into an alias at execution time. Users who want to send a contextual message, target a specific player, or pass an argument to a game command have to create a separate alias for every variation. Parameterization would let a single alias handle many variations cleanly.
FFXIV also has its own native targeting placeholders like <t>, <me>, <1> through <8>, and <r> that the game resolves natively at command execution time. These must pass through Silkstring completely untouched.
Acceptance Criteria
- Users can define parameter placeholders in their command sequences using a defined syntax
- Parameters are passed when invoking the alias, e.g.
/hello World passes World as a parameter
- Multiple parameters are supported, e.g.
/greet Oreo Kana passes two parameters
- Unset parameters either use a defined default value or are replaced with an empty string
- FFXIV native targeting placeholders like
<t>, <me>, <1> through <8>, and <r> pass through substitution completely untouched
- Existing aliases without parameters are completely unaffected
- Parameter syntax is discoverable in the EditWindow UI
Suggested solution
At execution time in the hook detour, after matching an alias, extract any text typed after the alias name as a parameter string. Split it into individual parameters and pass them through to CommandHandler.ExecuteAsync. Before firing each command, run a parameter substitution pass replacing placeholder tokens with the provided values. The substitution pass explicitly skips any token wrapped in angle brackets so FFXIV's native placeholders are preserved.
Suggested design
- Parameter syntax:
{1}, {2}, {3} etc - positional, curly brace delimited
- Everything typed after the alias name is treated as the parameter string, split on spaces
- Example: alias
hello with command say Hello {1}! invoked as /hello World fires say Hello World!
- Multiple parameters: alias
greet with command say Hello {1} and {2}! invoked as /greet Oreo Kana fires say Hello Oreo and Kana!
- Optional default values:
{1:stranger} uses "stranger" if no first parameter is provided
{0} is reserved as the entire parameter string unsplit, useful for passing a full sentence to /say or /yell
- Parameter substitution runs after variable substitution so both can be used together
- Angle bracket tokens are explicitly skipped during substitution so
<t>, <me>, <1> through <8>, <r> and any other FFXIV placeholders reach the game intact
- Add a parameters reference in EditWindow alongside the variables reference
Would Like to Have
- Named parameters:
{target} instead of {1} for more readable command sequences
- Parameter validation: mark a parameter as required so the alias refuses to fire with a chat error if it is missing rather than silently substituting an empty string
Testing Considerations
Happy path
Sad path
Problem/Opportunity Space
Currently alias command sequences are completely static - the same commands fire every time regardless of how the alias is invoked. There is no way to pass dynamic input into an alias at execution time. Users who want to send a contextual message, target a specific player, or pass an argument to a game command have to create a separate alias for every variation. Parameterization would let a single alias handle many variations cleanly.
FFXIV also has its own native targeting placeholders like
<t>,<me>,<1>through<8>, and<r>that the game resolves natively at command execution time. These must pass through Silkstring completely untouched.Acceptance Criteria
/hello WorldpassesWorldas a parameter/greet Oreo Kanapasses two parameters<t>,<me>,<1>through<8>, and<r>pass through substitution completely untouchedSuggested solution
At execution time in the hook detour, after matching an alias, extract any text typed after the alias name as a parameter string. Split it into individual parameters and pass them through to
CommandHandler.ExecuteAsync. Before firing each command, run a parameter substitution pass replacing placeholder tokens with the provided values. The substitution pass explicitly skips any token wrapped in angle brackets so FFXIV's native placeholders are preserved.Suggested design
{1},{2},{3}etc - positional, curly brace delimitedhellowith commandsay Hello {1}!invoked as/hello Worldfiressay Hello World!greetwith commandsay Hello {1} and {2}!invoked as/greet Oreo Kanafiressay Hello Oreo and Kana!{1:stranger}uses "stranger" if no first parameter is provided{0}is reserved as the entire parameter string unsplit, useful for passing a full sentence to/sayor/yell<t>,<me>,<1>through<8>,<r>and any other FFXIV placeholders reach the game intactWould Like to Have
{target}instead of{1}for more readable command sequencesTesting Considerations
Happy path
{0}passes the full parameter string unsplit<t>passes through substitution untouched<1>through<8>pass through untouched<me>passes through untouched<r>passes through untouchedSad path
{1does not crash the resolver