SpadsPluginApi - SPADS Plugin API
Perl:
package MyPlugin;
use SpadsPluginApi;
my $pluginVersion='0.1';
my $requiredSpadsVersion='0.11';
sub getVersion { return $pluginVersion; }
sub getRequiredSpadsVersion { return $requiredSpadsVersion; }
sub new {
my $class=shift;
my $self = {};
bless($self,$class);
slog("MyPlugin plugin loaded (version $pluginVersion)",3);
return $self;
}
1;
Python:
import perl
spads=perl.MyPlugin
pluginVersion = '0.1'
requiredSpadsVersion = '0.12.29'
def getVersion(pluginObject):
return pluginVersion
def getRequiredSpadsVersion(pluginName):
return requiredSpadsVersion
class MyPlugin:
def __init__(self,context):
spads.slog("MyPlugin plugin loaded (version %s)" % pluginVersion,3)
SpadsPluginApi
is a Perl module implementing the plugin API for SPADS. This API allows anyone to add new features as well as customize existing SPADS features (such as balancing algorithms, battle status presentation, players skills management, command aliases...).
This API relies on plugin callback functions (implemented by SPADS plugins), which can in turn call plugin API functions (implemented by SPADS core) and access shared SPADS data.
Plugins can be coded in Perl (since SPADS 0.11) or Python (since SPADS 0.12.29).
This documentation was written when SPADS was only supporting plugins coded in Perl, so types for function parameters and return values are described using Perl terminology, with Perl sigils (%
for hash, @
for array, $
for scalars). Python plugins just need to ignore these sigils and use their equivalent internal Python types instead (Python dictionaries instead of Perl hashes, Python lists instead of Perl arrays, Python tuples instead of Perl lists, Python None value instead of Perl undef value...).
In order to call functions from the plugin API, Python plugin modules must first import the special perl
module, and then use the global variable of this module named after the plugin name to call the functions (refer to the SYNOPSYS for an example of a Python plugin named MyPlugin
calling the slog
API function).
SPADS uses the Inline::Python
Perl module to interface Perl code with Python code. Unfortunately, some versions of this module don't auto-convert Perl strings entirely when used with Python 3 (Python 2 is unaffected): depending on the version of Python and the version of the Inline::Python
Perl module used by your system, it is possible that the Python plugin callbacks receive Python byte strings as parameters instead of normal Python strings. In order to mitigate this problem, the plugin API offers both a way to detect from the Python plugin code if current system is affected (by calling the get_flag
function with parameter 'use_byte_string'
), and a way to workaround the problem by calling a dedicated fix_string
function which fixes the string values if needed. For additional information regarding these Python specific functions of the plugin API, refer to the API FUNCTIONS - Python specific section. Python plugins can also choose to implement their own pure Python function which fixes strings coming from SPADS if needed like this for example:
def fix_spads_string(spads_string):
if hasattr(spads_string,'decode'):
return spads_string.decode('utf-8')
return spads_string
def fix_spads_strings(*spads_strings):
fixed_strings=[]
for spads_string in spads_strings:
fixed_strings.append(fix_spads_string(spads_string))
return fixed_strings
On Windows systems, Perl emulates the fork
functionality using threads. As the Inline::Python
Perl module used by SPADS to interface with Python code isn't thread-safe, the fork functions of the plugin API (forkProcess
and forkCall
) aren't available from Python plugins when running on a Windows system. On Windows systems, using native Win32 processes for parallel processing is recommended anyway. Plugins can check if the fork functions of the plugin API are available by calling the get_flag
Python specific plugin API function with parameter 'can_fork'
, instead of checking by themselves if the current system is Windows. Refer to the API FUNCTIONS - Python specific section for more information regarding this function.
Automatic asynchronous socket management (addSocket
plugin API function) is also unavailable for Python plugins on Windows systems (this is due to the file descriptor numbers being thread-specific on Windows, preventing SPADS from accessing sockets opened in Python interpreter scope). However, it is still possible to manage asynchronous sockets manually, for example by hooking the SPADS event loop (eventLoop
plugin callback) to perform non-blocking select
with 0 timeout (refer to Python select documentation). Plugins can check if the addSocket
function of the plugin API is available by calling the get_flag
Python specific plugin API function with parameter 'can_add_socket'
, instead of checking by themselves if the current system is Windows. Refer to the API FUNCTIONS - Python specific section for more information regarding this function.
The callback functions are called from SPADS core and implemented by SPADS plugins. SPADS plugins are actually Perl or Python classes instanciated as objects. So most callback functions are called as object methods and receive a reference to the plugin object as first parameter. The exceptions are the constructor (Perl: new
receives the class/plugin name as first parameter, Python: __init__
receives the plugin object being created as first parameter), and a few other callbacks which are called/checked before the plugin object is actually created: getVersion
and getRequiredSpadsVersion
(mandatory callbacks), getParams
and getDependencies
(optional callbacks).
To be valid, a SPADS plugin must implement at least these 3 callbacks:
new($pluginName,$context)
. . . . [Python] __init__(self,context)
This is the plugin constructor, it is called when SPADS (re)loads the plugin.
The $context
parameter is a string which indicates in which context the plugin constructor has been called: "autoload"
means the plugin is being loaded automatically at startup, "load"
means the plugin is being loaded manually using !plugin <pluginName> load
command, "reload"
means the plugin is being reloaded manually using !plugin <pluginName> reload
command.
getVersion($self)
returns the plugin version number (example: "0.1"
).
getRequiredSpadsVersion($pluginName)
returns the required minimum SPADS version number (example: "0.11"
).
SPADS plugins can use the core SPADS configuration system to manage their own configuration parameters. This way, all configuration management tools in place (parameter values checking, !reloadconf
etc.) can be reused by the plugins. To do so, the plugin must implement following configuration callback:
getParams($pluginName)
This callback must return a reference to an array containing 2 elements. The first element is a reference to a hash containing the plugin global settings declarations, the second one is the same but for plugin preset settings declarations. These hashes use setting names as keys, and references to array of allowed types as values. The types must be either strings that match the keys of the %paramTypes
hash defined in SpadsConf.pm file, or custom functions to implement custom value checks. Such custom value checking functions take 2 parameters: the value to check as first parameter and a boolean specifying if the value is the default value (i.e. first value declared in the definition, for preset settings) as second parameter. The function must return true
if the value is valid, or false
if it is invalid (refer to examples below).
As for global SPADS core settings, the global settings of the plugin cannot be changed dynamically except by editing and reloading the configuration files (for example by using the !reloadConf
command). The global settings are defined before the preset definition sections in the plugin configuration file. Only one definition is allowed for each global setting, and only one value can be configured in each global setting definition. Global settings aren't impacted by preset changes. Global settings should be used for the structural parameterization of the plugin, which isn't supposed to be modified during runtime and isn't useful from end user point of view (for example file/directory path settings...).
As for SPADS core preset settings, the preset settings of the plugin can be changed dynamically (using the !plugin <pluginName> set <settingName> <settingValue>
command for example, or simply by changing current global preset). The preset settings are defined in the preset definition sections of the plugin configuration file, after the global plugin settings. The preset settings can be defined multiple times (once in each preset declaration section). Multiple values can be configured in each preset setting definition (values are separated by pipe character |
, the first value is the default value applied when loading the preset and the remaining values are the other allowed values). Preset settings are impacted by preset changes. Preset settings should be used for settings that need to be visible by end users and/or modifiable easily at runtime.
Example of implementation in Perl:
my %globalPluginParams = ( MyGlobalSetting1 => ['integer'],
MyGlobalSetting2 => ['ipAddr']);
my %presetPluginParams = ( MyPresetSetting1 => ['readableDir','null'],
MyPresetSetting2 => ['bool', \&myCustomSettingValueCheck] );
sub myCustomSettingValueCheck {
my ($settingValue,$isDefault)=@_;
return $settingValue eq 'true' || $settingValue eq 'false'
}
sub getParams { return [\%globalPluginParams,\%presetPluginParams] }
Example of implementation in Python:
def myCustomSettingValueCheck(settingValue,isDefault):
return settingValue == 'true' or settingValue == 'false'
globalPluginParams = { 'MyGlobalSetting1': ['integer'],
'MyGlobalSetting2': ['ipAddr'] }
presetPluginParams = { 'MyPresetSetting1': ['readableDir','null'],
'MyPresetSetting2': ['bool', myCustomSettingValueCheck], };
def getParams(pluginName):
return [ globalPluginParams , presetPluginParams ]
In these examples, the preset setting MyPresetSetting2
is declared as supporting both the values of the predefined type "bool" and the values allowed by the custom function myCustomSettingValueCheck
. The predefined type "bool" allows values 0
and 1
. The custom function myCustomSettingValueCheck
allows values "true"
and "false"
. So in the end the allowed values for the preset setting MyPresetSetting2
are: 0
, 1
, "true"
and "false"
.
SPADS plugins can use data and functions from other plugins (dependencies). But this can only work if the plugin dependencies are loaded before the plugin itself. That's why following callback should be used by such dependent plugins to declare their dependencies, which will allow SPADS to perform the check for them. Also, SPADS will automatically unload dependent plugins when one of their dependencies is unloaded.
getDependencies($pluginName)
This callback must return the plugin dependencies (list of plugin names).
Example of implementation in Perl:
sub getDependencies { return ('SpringForumInterface','MailAlerts'); }
Example of implementation in Python:
def getDependencies(pluginName):
return ('SpringForumInterface','MailAlerts')
Following callbacks are triggered by events from various sources (SPADS, Spring lobby, Spring server...):
onBattleClosed($self)
This callback is called when the battle lobby of the autohost is closed.
onBattleOpened($self)
This callback is called when the battle lobby of the autohost is opened.
onGameEnd($self,\%endGameData)
This callback is called each time a game hosted by the autohost ends.
The \%endGameData
parameter is a reference to a hash containing all the data stored by SPADS concerning the game that just ended. It is recommended to use a data printing function (such as the Dumper
function from the standard Data::Dumper
module included in Perl core) to check the content of this hash for the desired data.
onJoinBattleRequest($self,$userName,$ipAddr)
This callback is called each time a client requests to join the battle lobby managed by the autohost.
$userName
is the name of the user requesting to join the battle
$ipAddr
is the IP address of the user requesting to join the battle
This callback must return:
0
if the user is allowed to join the battle
1
if the user isn't allowed to join the battle (without explicit reason)
"<explicit reason string>"
if the user isn't allowed to join the battle, with explicit reason
onJoinedBattle($self,$userName)
This callback is called each time a user joins the battle lobby of the autohost.
$userName
is the name of the user who just joined the battle lobby
onLeftBattle($self,$userName)
This callback is called each time a user leaves the battle lobby of the autohost.
$userName
is the name of the user who just left the battle lobby
onLobbyConnected($self,$lobbyInterface)
/!\ RENAMED TO onLobbySynchronized
/!\
This callback has been renamed to onLobbySynchronized
since SPADS v0.13.35. It can still be used under the name onLobbyConnected
for the sake of backward compatibility, however this name is misleading so its usage under this name is not recommended (the callback is only called when the lobby connection is fully synchronized, i.e. when all the initial commands sent by the lobby server after successfully logging in have been received).
The $lobbyInterface
parameter is the instance of the SpringLobbyInterface module used by SPADS.
onLobbyDisconnected($self)
This callback is called each time the autohost is disconnected from the lobby server.
onLobbyLoggedIn($self,$lobbyInterface)
This callback is called each time the autohost successfully logins on the lobby server. It is one of the three callbacks triggered when a new connection to the lobby server is established. These callbacks are called in following order:
1) onLobbyLogin
(called when trying to login)
2) onLobbyLoggedIn
(called when successfully logged in)
3) onLobbySynchronized
(called when state is synchronized with server)
The $lobbyInterface
parameter is the instance of the SpringLobbyInterface module used by SPADS.
Note: This callback is the ideal place for a plugin to register its lobby command handlers using the addLobbyCommandHandler
function of the plugin API, if this plugin needs to process the commands sent by the lobby server during the initial lobby state synchronization phase (i.e. commands sent before the LOGININFOEND
command). For plugins that do not require being called back during the initial lobby state synchronization phase, the onLobbySynchronized
callback should be used instead to register the lobby command handlers.
onLobbyLogin($self,$lobbyInterface)
This callback is called each time the autohost tries to login on the lobby server. It is one of the three callbacks triggered when a new connection to the lobby server is established. These callbacks are called in following order:
1) onLobbyLogin
(called when trying to login)
2) onLobbyLoggedIn
(called when successfully logged in)
3) onLobbySynchronized
(called when state is synchronized with server)
The $lobbyInterface
parameter is the instance of the SpringLobbyInterface module used by SPADS.
onLobbySynchronized($self,$lobbyInterface)
This callback is called each time the autohost completes the lobby state synchronization phase, which occurs after successfully logging in. It is one of the three callbacks triggered when a new connection to the lobby server is established. These callbacks are called in following order:
1) onLobbyLogin
(called when trying to login)
2) onLobbyLoggedIn
(called when successfully logged in)
3) onLobbySynchronized
(called when state is synchronized with server)
The $lobbyInterface
parameter is the instance of the SpringLobbyInterface module used by SPADS.
Note: This callback is the ideal place for a plugin to register its lobby command handlers using the addLobbyCommandHandler
function of the plugin API, as long as this plugin does not need to process the commands sent by the lobby server during the initial lobby state synchronization phase (i.e. commands sent before the LOGININFOEND
command). For plugins that require being called back during the initial lobby state synchronization phase, the onLobbyLoggedIn
callback must be used instead to register the lobby command handlers.
onPresetApplied($self,$oldPresetName,$newPresetName)
This callback is called each time a global preset is applied.
$oldPresetName
is the name of the previous global preset
$newPresetName
is the name of the new global preset
onPrivateMsg($self,$userName,$message)
This callback is called each time the autohost receives a private message.
$userName
is the name of the user who sent a private message to the autohost
$message
is the private message received by the autohost
This callback must return:
0
if the message can be processed by other plugins and SPADS core
1
if the message must not be processed by other plugins and SPADS core (this prevents logging)
onReloadConf($self,$keepSettings)
This callback is called each time the SPADS configuration is reloaded.
$keepSettings
is a boolean parameter indicating if current settings must be kept.
This callback must return:
0
if an error occured while reloading the plugin configuration
1
if the plugin configuration has been reloaded correctly
onSettingChange($self,$settingName,$oldValue,$newValue)
This callback is called each time a setting of the plugin configuration is changed (using !plugin <pluginName> set ...
command).
$settingName
is the name of the updated setting
$oldValue
is the previous value of the setting
$newValue
is the new value of the setting
onSpringStart($self,$springPid)
This callback is called each time a Spring process is launched to host a game.
$springPid
is the PID of the Spring process that has just been launched.
onSpringStop($self,$springPid)
This callback is called each time the Spring process ends.
$springPid
is the PID of the Spring process that just ended.
onUnload($self,$context)
This callback is called when the plugin is unloaded. If the plugin has added handlers for SPADS command, lobby commands, or Spring commands, then they must be removed here. If the plugin has added timers or forked process callbacks, they should also be removed here. If the plugin handles persistent data, then these data must be serialized and written to persistent storage here.
The $context
parameter is a string which indicates in which context the callback has been called: "exiting"
means the plugin is being unloaded because SPADS is exiting, "restarting"
means the plugin is being unloaded because SPADS is restarting, "unload"
means the plugin is being unloaded manually using !plugin <pluginName> unload
command, "reload"
means the plugin is being reloaded manually using !plugin <pluginName> reload
command.
onVoteRequest($self,$source,$user,\@command,\%remainingVoters)
This callback is called each time a vote is requested by a player.
$source
indicates the way the vote has been requested ("pv"
: private lobby message, "battle"
: battle lobby message, "chan"
: master lobby channel message, "game"
: in game message)
$user
is the name of the user requesting the vote
\@command
is an array reference containing the command for which a vote is requested
\%remainingVoters
is a reference to a hash containing the players allowed to vote. This hash is indexed by player names. Perl plugins can filter these players by removing the corresponding entries from the hash directly, but Python plugins must use the alternate method based on the return value described below.
This callback must return 0
to prevent the vote call from happening, or 1
to allow it without changing the remaining voters list, or an array reference containing the player names that should be removed from the remaining voters list.
onVoteStart($self,$user,\@command)
This callback is called each time a new vote poll is started.
$user
is the name of the user who started the vote poll
\@command
is an array reference containing the command for which a vote is started
onVoteStop($self,$voteResult)
This callback is called each time a vote poll is stoped.
$voteResult
indicates the result of the vote: -1
(vote failed), 0
(vote cancelled), 1
(vote passed)
postSpadsCommand($self,$command,$source,$user,\@params,$commandResult)
This callback is called each time a SPADS command has been called.
$command
is the name of the command (without the parameters)
$source
indicates the way the command has been called ("pv"
: private lobby message, "battle"
: battle lobby message, "chan"
: master lobby channel message, "game"
: in game message)
$user
is the name of the user who called the command
\@params
is a reference to an array containing the parameters of the command
$commandResult
indicates the result of the command (if it is defined and set to 0
then the command failed, in all other cases the command succeeded)
preGameCheck($self,$force,$checkOnly,$automatic)
This callback is called each time a game is going to be launched, to allow plugins to perform pre-game checks and prevent the game from starting if needed.
$force
is 1
if the game is being launched using !forceStart
command, 0
else
$checkOnly
is 1
if the callback is being called in the context of a vote call, 0
else
$automatic
is 1
if the game is being launched automatically through autoStart functionality, 0
else
The return value must be the reason for preventing the game from starting (for example "too many players for current map"
), or 1
if no reason can be given, or undef to allow the game to start.
preSpadsCommand($self,$command,$source,$user,\@params)
This callback is called each time a SPADS command is called, just before it is actually executed. This callback is called after the commandRightsOverride
callback.
$command
is the name of the command (without the parameters)
$source
indicates the way the command has been called ("pv"
: private lobby message, "battle"
: battle lobby message, "chan"
: master lobby channel message, "game"
: in game message)
$user
is the name of the user who called the command
\@params
is a reference to an array containing the parameters of the command
This callback must return 0
to prevent the command from being processed by other plugins and SPADS core, or 1
to allow it.
Following callbacks are called by SPADS during specific operations to allow plugins to customize features (more callbacks can be added on request):
addStartScriptTags($self,\%additionalData)
This callback is called when a Spring start script is generated, just before launching the game. It allows plugins to declare additional scrip tags which will be written in the start script.
\%additionalData
is a reference to a hash which must be updated by Perl plugins by adding the desired keys/values. For example a Perl plugin can add a modoption named hiddenoption
with value test
like this: $additionalData{"game/modoptions/hiddenoption"}="test"
. For tags to be added in player sections, the special key playerData
must be used. This special key must point to a hash associating each account ID to a hash containing the tags to add in the corresponding player section (subsections can be created by using nested hashes). For tags to be added in AI bot sections, the special key aiData
must be used. This special key must point to a hash associating each AI bot name to a hash containing the tags to add in the corresponding AI bot section (subsections can be created by using nested hashes).
Note for Python plugins: As Python plugins cannot modify the data structures passed as parameters to the callbacks, an alternate way to implement this callback is offered. Instead of modifying the additionnalData
dictionary directly, the callback can return a new dictionary containing the entries which must be added. For example a Python plugin can add a tag named CommanderLevel
set to value 8
in the player section of the player whose account ID is 1234
like this: return {'playerData': { '1234': { 'CommanderLevel': 8 } } }
balanceBattle($self,\%players,\%bots,$clanMode,$nbTeams,$teamSize)
This callback is called each time SPADS needs to balance a battle and evaluate the resulting balance quality. It allows plugins to replace the built-in balance algorithm.
\%players
is a reference to a hash containing the players in the battle lobby. This hash is indexed by player names, and the values are references to a hash containing player data. For balancing, you should only need to access the players skill as follows: $players->{<playerName>}->{skill}
\%bots
is a reference to a hash containing the bots in the battle lobby. This hash has the exact same structure as \%players
.
$clanMode
is the current clan mode which must be applied to the balance. Clan modes are specified here. <maxUnbalance>
thresholds are automatically managed by SPADS, plugins don't need to handle them. So basically, plugins only need to check if tag
and/or pref
clan modes are enabled and apply them to their balance algorithm.
$nbTeams
and $teamSize
are the target battle structue computed by SPADS. The number of entities to balance is the number of entries in \%players
+ number of entries in \%bots
. The number of entities to balance is always > $nbTeams*($teamSize-1)
, and <= $nbTeams*$teamSize
.
If the plugin is unable to balance the battle, it must not update \%players
and \%bots
. The callback must return undef or a negative value so that SPADS knows it has to use another plugin or the internal balance algorithm instead.
If the plugin is able to balance the battle, it can use two methods to transmit the desired balance to SPADS (Python plugins can only use the second method):
The first method consists in updating directly the \%players
and \%bots
hash references with the team and id information. Assigned player teams must be written in $players->{<playerName>}->{battleStatus}->{team}
, and assigned player ids must be written in $players->{<playerName>}->{battleStatus}->{id}
. The \%bots
hash reference works the same way. The return value is the unbalance indicator, defined as follows: standardDeviationOfTeamSkills * 100 / averageTeamSkill
.
The second method consists in returning an array reference containing the balance information instead of directly editing the \%players
and \%bots
parameters. The returned array must contain 3 items: the unbalance indicator (as defined in first method description above), the player assignation hash and the bot assignation hash. The player assignation hash and the bot assignation hash have exactly the same structure: the keys are the player/bot names and the values are hashes containing team
and id
items with the corresponding values for the balanced battle.
canBalanceNow($self)
This callback allows plugins to delay the battle balance operation. It is called each time a battle balance operation is required (either automatic if autoBalance is enabled, either manual if !balance
command is called). If the plugin is ready for balance, it must return 1
. Else, it can delay the operation by returning 0
(the balance algorithm won't be launched as long as the plugin didn't return 1
).
changeUserAccessLevel($self,$userName,\%userData,$isAuthenticated,$currentAccessLevel)
This callback is called by SPADS each time it needs to get the access level of a user. It allows plugins to overwrite this level. Don't call the getUserAccessLevel($user)
function from this callback, or the program will be locked in recursive loop! (and it would give you the same value as $currentAccessLevel
anyway).
\%userData
is a reference to a hash containing the lobby data of the user
$isAuthenticated
indicates if the user has been authenticated (0: lobby server in LAN mode and not authenticated at autohost level, 1: authenticated by lobby server only, 2: authenticated by autohost)
The callback must return the new access level value if changed, or undef if not changed.
commandRightsOverride($self,$lowerCaseCommandName,\@command,$source,$user,$effectiveUserAccessLevel,$userAccessLevel,\%requiredAccessLevels)
This callback is called each time a SPADS command is called by a user, just before checking the user access level requirements. It allows plugins to bypass this check and implement their own logic to allow or disallow the command execution. This callback is called before the preSpadsCommand
callback, which can still be used to prevent the command execution later in the workflow even though the commandRightsOverride
callback allowed it.
$lowerCaseCommandName
is the name of the command being called (in lowercase)
\@command
is an array reference containing the full command being called
$source
indicates the way the command was called ("pv"
: private lobby message, "battle"
: battle lobby message, "chan"
: master lobby channel message, "game"
: in game message)
$user
is the name of the user who called the command
$effectiveUserAccessLevel
is the effective access level of the user who called the command (taking boss mode into account if applicable)
$userAccessLevel
is the original access level of the user who called the command (ignoring boss mode)
\%requiredAccessLevels
is a reference to a hash containing the access levels normally required to call the command in current context. The hash keys are directLevel
for the access level required to call the command directly, and voteLevel
for the access level required to call a vote for the command. The values can be undefined or empty string when there is no access level associated (i.e. the command cannot be called), or the corresponding required access level value (integer).
The return value of the callback determines whether the default access level requirements for the command must be bypassed. If an undefined value is returned, the default behavior is applied (no bypass of access level requirements). If a true value is returned, the access level requirements are bypassed and the user is allowed to call the command directly. If a false value is returned, the user is denied the right to call the command directly, regardless of his access level.
delayShutdown($self)
This callback is called by SPADS each time it needs to quit or restart. It allows plugins to delay the shutdown operation, which can be useful to prevent SPADS from exiting before a process forked by the plugin ends for example.
The callback must return a false value if SPADS can quit right now, or a true value if SPADS must wait before exiting.
filterRotationMaps($self,\@rotationMaps)
This callback is called by SPADS each time a new map must be picked up for rotation. It allows plugins to remove some maps from the rotation maps list just before the new map is picked up.
\@rotationMaps
is a reference to an array containing the names of the maps currently allowed for rotation.
The callback must return a reference to a new array containing the filtered map names.
fixColors($self,\%players,\%bots,\%battleStructure)
This callback is called each time SPADS needs to fix the teams colors. It allows plugins to replace the built-in color fixing algorithm.
\%players
is a reference to a hash containing the players currently in the battle lobby. This hash is indexed by player names, and the values are references to hashes containing following player data: team
(team number), id
(id number) and color
(current color configured in lobby, i.e. a hash containing keys "red"
, "green"
, "blue"
and whose values are numbers between 0 and 255 included).
\%bots
is a reference to a hash containing the bots currently in the battle lobby. This hash has the exact same structure as \%players
.
\%battleStructure
is a reference to a hash containing data concerning the battle structure. This parameter is provided to plugins for ease of use but actually these data are redundant with the data already provided in the two previous parameters (the %players
and %bots
hashes), they are just organized in a different way. The %battleStructure
hash is indexed by team numbers. For each team number, the associated value is a reference to a hash indexed by the ID numbers contained in the team. For each ID number, the associated value is a reference to a hash containing the two following keys: players
(the associated value is a reference to an array containing the names of the players belonging to this ID) and bots
(the associated value is a reference to an array containing the names of the AI bots belonging to this ID).
If the plugin is unable to fix colors, then it must return undef
so that SPADS knows it has to use another plugin or the internal color fixing algorithm instead.
If the plugin is able to fix the players and AI bots colors, then it must return a reference to a hash containing all colors assignations, indexed by ID numbers. The keys must be the ID numbers and the values are references to hash whose keys are "red"
, "green"
and "blue"
and values are the corresponding RGB values (between 0 and 255 included) of the color assigned to the ID.
setMapStartBoxes($self,\@boxes,$mapName,$nbTeams,$nbExtraBox)
This callback allows plugins to set map start boxes (for "Choose in game" start position type).
\@boxes
is a reference to an array containing the start boxes definitions. A start box definition is a string containing the box coordinates separated by spaces, in following order: left, top, right, bottom (0,0 is top left corner and 200,200 is bottom right corner). If the array already contains box definitions, it means SPADS already knows boxes for this map.
$mapName
is the name of the map for which start boxes are requested
$nbTeams
is the current number of teams configured (at least this number of start boxes must be provided)
$nbExtraBox
is the number of extra box required. Usually this is 0, unless a special game mode is enabled such as King Of The Hill.
If the plugin isn't able or doesn't need to provide/override start boxes, it must not update the \@boxes
array. It must return 0
so that SPADS knows it has to check other plugins for possible start boxes.
If the plugin needs to provide/override start boxes, it can use two methods to transmit the start box definitions (Python plugins can only use the second method):
The first method consists in replacing the \@boxes
array content directly with the new desired start box definitions. If other plugins should be allowed to replace the start box definitions, the callback must return 0
, else it must return 1
.
The second method consists in returning an array reference containing the new start box definitions instead of directly updating the \@boxes
parameter. The returned array must contain 2 items: the normal return value as first item (0
to allow other plugins to replace the start boxes, or 1
else), and an array reference containg the new start box definitions as second item.
setVoteMsg($self,$reqYesVotes,$maxReqYesVotes,$reqNoVotes,$maxReqNoVotes,$nbRequiredManualVotes)
This callback allows plugins to customize the vote status messages.
$reqYesVotes
is the total number of "yes" votes required for vote to pass (if away-voters don't vote).
$reqNoVotes
is the total number of "no" votes required for vote to fail (if away-voters don't vote).
$maxReqYesVotes
is the maximum total number of "yes" votes required for vote to pass (if all away-voters come back and vote).
$maxReqNoVotes
is the maximum total number of "no" votes required for vote to fail (if all away-voters come back and vote).
$nbRequiredManualVotes
is the minimum number of manual votes required for vote to be taken into account.
The callback must return a list containing following 2 elements: the lobby vote message, and the in-game vote message (undef values can be used to keep default messages).
updateCmdAliases($self,\%aliases)
This callback allows plugins to add new SPADS command aliases by adding new entries in the \%aliases
hash reference. This hash is indexed by alias names and the values are references to an array containing the associated command. For example, a Perl plugin can add an alias "!cvmap ...
" for "!callVote map ...
" like this: $aliases->{cvmap}=['callVote','map']
"%<N>%"
can be used as placeholders for original alias command parameters. For example, a Perl plugin can add an alias "!iprank <playerName>
" for "!chrank <playerName> ip
" like this: $aliases->{iprank}=['chrank','%1%','ip']
Note for Python plugins: As Python plugins cannot modify the data structures passed as parameters to the callbacks, an alternate way to implement this callback is offered. Instead of modifying the aliases
dictionary directly, the callback can return a new dictionary containing the alias entries which must be added.
updatePlayerSkill($self,\%playerSkill,$accountId,$modName,$gameType)
This callback is called by SPADS each time it needs to get or update the skill of a player (on battle join, on game type change...). This allows plugins to replace the built-in skill estimations (rank, TrueSkill...) with custom skill estimations (ELO, Glicko ...).
\%playerSkill
is a reference to a hash containing the skill data of the player. A Perl plugin can update the skill
entry as follows: $playerSkill->{skill}=<skillValue>
. The skill uncertainty can also be updated by plugins, by updating the sigma
entry as follows: $playerSkill->{sigma}=<skillUncertaintyValue>
.
$accountId
is the account ID of the player for whom skill value is requested.
$modName
is the currently hosted MOD (example: "Balanced Annihilation V7.72"
)
$gameType
is the current game type ("Duel"
, "Team"
, "FFA"
or "TeamFFA"
)
The return value is the skill update status: 0
(skill not updated by the plugin), 1
(skill updated by the plugin), 2
(skill updated by the plugin in degraded mode)
Note for Python plugins: As Python plugins cannot modify the data structures passed as parameters to the callbacks, an alternate way to implement this callback is offered. Instead of modifying the playerSkill
dictionary directly, the callback can return a list containing the normal return value as first item (described above), the new skill value as second item, and optionally the new skill uncertainty value as third item.
updateGameStatusInfo($self,\%playerStatus,$accessLevel)
This callback is called by SPADS for each player in game when the !status
command is called, to allow plugins to update and/or add data which will be presented to the user issuing the command.
\%playerStatus
is a reference to the hash containing current player status data. A Perl plugin can update existing data or add new data in this hash. For example: $playerStatus->{myPluginData}=<myPluginValue>
$accessLevel
is the autohost access level of the user issuing the !status
command.
The return value must be a reference to an array containing the names of the status information updated or added by the plugin.
Note for Python plugins: As Python plugins cannot modify the data structures passed as parameters to the callbacks, an alternate way to implement this callback is offered. Instead of modifying the playerStatus
dictionary directly, the callback can return a new dictionary containing the data to add/modify in the playerStatus
dictionary.
updateStatusInfo($self,\%playerStatus,$accountId,$modName,$gameType,$accessLevel)
This callback is called by SPADS for each player in the battle lobby when the !status
command is called, to allow plugins to update and/or add data which will be presented to the user issuing the command.
\%playerStatus
is a reference to the hash containing current player status data. A Perl plugin can update existing data or add new data in this hash. For example: $playerStatus->{myPluginData}=<myPluginValue>
$accountId
is the account ID of the player for whom status data update is requested.
$modName
is the currently hosted MOD (example: "Balanced Annihilation V7.72"
)
$gameType
is the current game type ("Duel"
, "Team"
, "FFA"
or "TeamFFA"
)
$accessLevel
is the autohost access level of the user issuing the !status
command.
The return value must be a reference to an array containing the names of the status information updated or added by the plugin.
Note for Python plugins: As Python plugins cannot modify the data structures passed as parameters to the callbacks, an alternate way to implement this callback is offered. Instead of modifying the playerStatus
dictionary directly, the callback can return a new dictionary containing the data to add/modify in the playerStatus
dictionary.
SPADS uses the asynchronous programming paradigm, so it is based on a main event loop. The following callback is called during each iteration of this event loop:
eventLoop($self)
Warning: this callback is called very frequently (during each iteration of SPADS main event loop), so performing complex operations here can be very intensive on the CPU. It is recommended to use timers (addTimer
/removeTimer
functions) instead for all time related operations (timeouts, scheduled actions, regular serialization of persistent data to avoid data loss...). This callback shouldn't be blocking, otherwise SPADS may become unstable.
The API functions are implemented by SPADS core and can be called by SPADS plugins (directly from Perl plugins, or via spads.[...]
from Python plugins).
getBosses()
This accessor returns a reference to the hash containing the names of the bosses in the battle lobby (if the hash is empty, the boss mode is disabled).
getConfMacros()
This accessor returns a reference to the hash containing the configuration macros used to (re)start SPADS.
getCurrentVote()
This accessor returns a reference to a hash containing information regarding votes.
If there is no vote in progress and the last vote succeeded, then the returned hash is always empty.
If there is no vote in progress and the last vote failed, then the content of the returned hash depends on the delay since the last vote ended. If the delay is greater than the reCallVoteDelay, then the returned hash is empty, else it contains the two following keys:
user
: the name of the user who started the last vote
expireTime
: the time when the last vote failed (in UNIX timestamp format)
If there is a vote in progress, then the returned hash contains following keys:
user
: the name of the user who started the vote
expireTime
: the time when the vote will timeout, in UNIX timestamp format
awayVoteTime
: the time when the automatic votes for away users (see voteMode preference) will be taken into account, in UNIX timestamp format. This field is reset to zero when the corresponding time is reached and votes for away users are triggered.
source
: the source of the message which started the vote (either "pv"
, "chan"
, "game"
or "battle"
)
command
: a reference to an array containg the command being voted (the first element is the command name, the other elements are the command parameters)
remainingVoters
: a reference to a hash whose keys are the names of the players allowed to vote who didn't vote yet
yesCount
: current number of "yes" votes
noCount
: current number of "no" votes
blankCount
: current number of "blank" votes
awayVoters
: a reference to a hash whose keys are the names of the players who auto-voted blank due to being away (see voteMode preference)
manualVoters
: a reference to a hash whose keys are the names of the players who voted manually, and the values are the actual votes ("yes"
, "no"
or "blank"
)
Note: An easy way to check if a vote is currently in progress consists in calling getCurrentVote()
and checking if the returned hash contains the command
key. If the hash contains the command
key then it means a vote is in progress, else it means no vote is in progress.
getLobbyInterface()
This accessor returns the instance of the SpringLobbyInterface module used by SPADS.
Following methods, called on the SpringLobbyInterface
object, can be useful to plugins for accessing various lobby data:
- getUsers()
This method returns a reference to a hash containing the data regarding all the online users. The hash is indexed by player names and the values are references to hashes with following content:
accountId
: the lobby account ID of the user
country
: the country code of the user (2 characters)
ip
: the IP address of the user, if known (undef
else)
lobbyClient
: the name of the lobby client software used by the user
status
: the lobby status of the user, which is itself a reference to another hash, containing following content: access
(0
: normal user, 1
: moderator), away
(0
: active, 1
: away), bot
(0
: human, 1
: bot), inGame
(0
: out of game, 1
: in game), rank
(integer between 0 and 7 included)
Note 1: this method performs a deep copy of the data to prevent external code from corrupting internal data. However it is also possible to read the same data directly without triggering a deep copy by accessing the users
field of the SpringLobbyInterface
object.
Note 2: if you need to retrieve users indexed by lobby account IDs instead of names, you can access the accounts
field of the SpringLobbyInterface
object. It contains a reference to a hash whose keys are the lobby account IDs and values are the lobby user names.
- getChannels()
This method returns a reference to a hash containing the data regarding all the lobby channels joined by SPADS. The hash is indexed by channel names and the values are references to hashes with following content:
topic
: a reference to a hash with following content: author
(the name of the user who set the topic), content
(the topic content)
users
: a reference to a hash whose keys are the names of the users in the lobby channel
Note: this method performs a deep copy of the data to prevent external code from corrupting internal data. However it is also possible to read the same data directly without triggering a deep copy by accessing the channels
field of the SpringLobbyInterface
object.
- getBattles()
This method returns a reference to a hash containing the data regarding all the battle lobbies currently hosted on the lobby server. The hash is indexed by battle ID and the values are references to hashes with following content:
engineName
: the name of the engine used by the battle lobby (usually "spring"
)
engineVersion
: the version of the engine used by the battle lobby (example: "105.0"
)
founder
: the name of the user who created the battle lobby
ip
: the IP address used by the battle lobby for game hosting
locked
: the lock status of the battle lobby (0
: unlocked, 1
: locked)
map
: the map currently selected in the battle lobby
mapHash
: the hash of the map currently selected in the battle lobby (computed by the unitsync library)
maxPlayers
: the battle lobby size (maximum number of players who can be in the battle lobby, ignoring spectators)
mod
: the mod (game name) used by the battle lobby
natType
: the type of NAT traversal method used by the host (0
: none, 1
: hole punching, 2
: fixed source ports)
nbSpec
: the number of spectators currently in the battle lobby
passworded
: the password status of the battle lobby (0
: not password protected, 1
: password protected)
port
: the port used by the battle lobby for game hosting
rank
: the minimum rank limit used by the battle lobby
title
: the description of the battle lobby
userList
: a reference to an array containing the names of the users currently in the battle lobby
Note: this method performs a deep copy of the data to prevent external code from corrupting internal data. However it is also possible to read the same data directly without triggering a deep copy by accessing the battles
field of the SpringLobbyInterface
object.
- getBattle()
This method returns a reference to a hash containing the data regarding the battle lobby currently hosted by SPADS. This hash has following content:
battleId
: the battle ID of the battle lobby
botList
: a reference to an array containing the names of the AI bots currently in the battle lobby
bots
: a reference to a hash containing the data regarding the AI bots currently in the battle lobby. This hash is indexed by AI bot names and the values are references to hashes with following content: aiDll
(details regarding the AI bot, usually the AI name and version, or the AI DLL), battleStatus
(data representing the status of the AI bot in the battle lobby, see BATTLESTATUS hash description below), color
(data specifying the team color of the AI bot using RGB model, see COLOR hash description below), owner
(name of the user hosting the AI bot)
restrictedUnits
: a reference to a hash whose keys are the names of the game units currently restricted, and values are the corresponding unit limit.
modHash
: the hash of the mod (game) used by the battle lobby
password
: the password used to protect the battle lobby ("*"
if no password is set)
scriptTags
: a reference to a hash containing all the script tags (in lower case) and their associated values (used to generate the start script)
startRects
: a reference to a hash containing the start box definitions. This hash is indexed by box numbers and the values are references to hashes containing the box coordinates (top
, left
, bottom
and right
) in the 0-200
range (0,0
is the top left corner and 200,200
is the bottom right corner).
users
: a reference to a hash containing the data regarding the users currently in the battle lobby. This hash is indexed by user names and the values are references to hashes with following content: battleStatus
(data representing the status of the player in the battle lobby, see BATTLESTATUS hash description below), color
(data specifying the team color of the player using RGB model, see COLOR hash description below), ip
(IP address of the user if known, undef
else), port
(client port of the user if known, undef
else), and optionally scriptPass
if the client provided a script password when joining the battle lobby.
BATTLESTATUS hash description:
bonus
: resource bonus value (integer in 0-100
range, 0
means no bonus)
id
: player team number (starting at 0
)
mode
: player/spectator mode (0
: spectator, 1
: player)
ready
: ready state (0
: not ready, 1
: ready)
side
: game faction number
sync
: synchronization status (0
: unsynchronized, 1
: synchronized)
team
(ally team number, starting at 0
)
COLOR hash description:
red
: red component intensity (integer in 0-255
range)
green
: green component intensity (integer in 0-255
range)
blue
: blue component intensity (integer in 0-255
range)
Note: this method performs a deep copy of the data to prevent external code from corrupting internal data. However it is also possible to read the same data directly without triggering a deep copy by accessing the battle
field of the SpringLobbyInterface
object.
getLobbyState()
This accessor returns an integer describing the current lobby state. The corresponding constants are provided to ease lobby state handling/comparisons, as listed below:
0
- LOBBY_STATE_DISCONNECTED
(disconnected from lobby server)
1
- LOBBY_STATE_CONNECTING
(connecting to lobby server)
2
- LOBBY_STATE_CONNECTED
(connected to lobby server but not logged in yet)
3
- LOBBY_STATE_LOGGED_IN
(logged in but not synchronized yet)
4
- LOBBY_STATE_SYNCHRONIZED
(synchronized, i.e all the commands describing the initial state of the lobby have been received from server)
5
- LOBBY_STATE_OPENING_BATTLE
(opening battle)
6
- LOBBY_STATE_BATTLE_OPENED
(battle opened)
Perl plugins can use these constants directly in the plugin code, like this for example:
if(getLobbyState() >= LOBBY_STATE_CONNECTED) {
slog("SPADS is connected to lobby server",3);
}
Python plugins must call them as SPADS functions, like this for example:
if spads.getLobbyState() >= spads.LOBBY_STATE_CONNECTED():
spads.slog("SPADS is connected to lobby server",3)
getPluginList()
This accessor returns a reference to an array containing the names of the plugins currently loaded (in load order).
getRunningBattle()
This accessor returns a reference to a hash representing the state of the battle lobby hosted by SPADS when the game currently running was launched. This is useful to find the actual characteristics of the currently running game (battle structure, settings...), because things might have changed in the battle lobby since the game started (players joined/left, map changed...) so the current battle lobby data aren't necessarily consistent with the game currently running.
If no game is in progress, this hash is empty.
If a game is in progress, the hash contains the same data as the data returned by the getBattle()
and getBattles()
methods of the SpringLobbyInterface
object (see getLobbyInterface()
accessor) when the game was launched. Concerning the getBattles()
data, only the data related to the battle lobby hosted by SPADS are included in the hash.
getSpadsConf()
getSpadsConfFull()
getSpringInterface()
getSpringPid()
getSpringServerType()
getTimestamps()
getUserPref($userName,$prefName)
This accessor returns the current value of a user's preference.
getPlugin($pluginName=caller())
This function returns the plugin object matching the plugin name given as parameter $pluginName
. If no parameter is provided, the plugin name of the plugin calling the function is used.
getPluginConf($pluginName=caller())
This function returns the plugin configuration for the plugin named $pluginName
. If no parameter is provided, the plugin name of the plugin calling the function is used. The return value is a reference to a hash using plugin settings names as keys and plugin settings values as values.
addLobbyCommandHandler(\%handlers,$priority=caller(),$isPreCallback)
This function allows plugins to set up their own handlers for Spring lobby commands received by SPADS from lobby server.
\%handlers
is a reference to a hash which contains the handlers to be added: each entry associates a lobby command (in uppercase) to a handler function implemented by the plugin. For example, with { JOINBATTLEREQUEST => \&hLobbyJoinBattleRequest }
, the plugin has to implement the function hLobbyJoinBattleRequest
. The parameters passed to the handlers are the command tokens: the command name followed by command parameters. Refer to Spring lobby protocol specifications for more information.
$priority
is the priority of the handlers. Lowest priority number actually means higher priority. If not provided, the plugin name is used as priority, which means it is executed after handlers having priority < 1000, and before handlers having priority > 1000. Usually you don't need to provide priority, unless you use data managed by other handlers.
$isPreCallback
specifies whether the command handlers must be called before or after the lobby interface module handlers. If this parameter is set to a true value, the command handlers will be called before the lobby interface module handlers. If this parameter is not provided or set to a false value, the command handlers will be called after the lobby interface module handlers.
Note: As all lobby command handlers are automatically removed by SPADS when it is disconnected from the lobby server (due to network problems for example), plugins should always re-set up their lobby command handlers each time SPADS successfully reconnects. This can be done automatically by doing the addLobbyCommandHandler
call in the onLobbySynchronized
event-based callback (for plugins that don't need to process the commands sent by the lobby server during the initial lobby state synchronization phase) or in the onLobbyLoggedIn
event-based callback (for plugins that need to process the commands sent by the lobby server during the initial lobby state synchronization phase).
addSpadsCommandHandler(\%handlers,$replace=0)
This function allows plugins to add or replace SPADS command handlers.
\%handlers
is a reference to a hash which contains the handlers to be added or replaced: each entry associates a SPADS command to a handler function implemented by the plugin. For example, with { myCommand => \&hSpadsMyCommand }
, the plugin has to implement the function hSpadsMyCommand
. The parameters passed to the handlers are: $source
,$userName
,\@params
,$checkOnly
.
$source
indicates the way the command has been called ("pv"
: private lobby message, "battle"
: battle lobby message, "chan"
: master lobby channel message, "game"
: in game message)
$userName
is the name of the user issuing the command
\@params
is a reference to an array containing the command parameters
$checkOnly
indicates that the command must not be executed but only checked for consistency (this mode is used for !callVote command)
If the command cannot be executed (invalid syntax ...) the handler must return 0
. If the command is correct but requires automatic parameter adjustments (automatic case correction or name completion for example), a reference to an array containing the adjusted command must be returned. If it can be executed directly without any adjustment, 1
must be returned.
$replace
indicates if the handlers provided can replace existing ones: 0
means add handlers only if there is no handler for the given command (default), 1
means add or replace if existing.
addSpringCommandHandler(\%handlers,$priority=caller())
This function allows plugins to set up their own handlers for Spring AutoHost commands received by SPADS from Spring server.
\%handlers
is a reference to a hash which contains the handlers to be added: each entry associates a Spring AutoHost command to a handler function implemented by the plugin. The Spring AutoHost command names must match the values of %commandCodes
defined in SpringAutoHostInterface.pm. For example, with { SERVER_STARTED => \&hSpringServerStarted }
, the plugin has to implement the function hSpringServerStarted
. The parameters passed to the handlers are the command tokens: the command name followed by command parameters. Refer to Spring autohost protocol specifications (from source comments) for more information.
$priority
is the priority of the handlers. Lowest priority number actually means higher priority. If not provided, the plugin name is used as priority, which means it is executed after handlers having priority < 1000, and before handlers having priority > 1000. Usually you don't need to provide priority, unless you use data managed by other handlers.
removeLobbyCommandHandler(\@commands,$priority=caller(),$isPreCallback)
This function must be called by plugins which added lobby command handlers previously using addLobbyCommandHandler
function, when these handlers are no longer required (for example in the onUnload
callback, when the plugin is unloaded).
\@commands
is a reference to an array containing the lobby command names (in uppercase) for which the handlers must be removed.
$priority
is the priority of the handlers to remove. It must be the same as the priority used when adding the handlers. If not provided, the plugin name is used as priority. Usually you don't need to provide priority, unless you use data managed by other handlers.
$isPreCallback
specifies the type of command handlers to remove (must match the value used for the addLobbyCommandHandler
function call for these handlers)
removeSpadsCommandHandler(\@commands)
This function must be called by plugins which added SPADS command handlers previously using addSpadsCommandHandler
function, when these handlers are no longer required (for example in the onUnload
callback, when the plugin is unloaded).
\@commands
is a reference to an array containing the SPADS command names (in uppercase) for which the handlers must be removed.
removeSpringCommandHandler(\@commands,$priority=caller())
This function must be called by plugins which added Spring AutoHost command handlers previously using addSpringCommandHandler
function, when these handlers are no longer required (for example in the onUnload
callback, when the plugin is unloaded).
\@commands
is a reference to an array containing the Spring AutoHost command names for which the handlers must be removed.
$priority
is the priority of the handlers to remove. It must be the same as the priority used when adding the handlers. If not provided, the plugin name is used as priority. Usually you don't need to provide priority, unless you use data managed by other handlers.
applyPreset($presetName)
cancelCloseBattle()
cancelQuit($reason)
closeBattle($reason,$silentMode=0)
This function makes SPADS close current battle lobby.
The $reason
parameter must be a string containing the reason for closing the battle lobby.
The $silentMode
parameter is an optional boolean parameter specifying if the broadcast message (which is normally sent when the battle lobby is closed) must be prevented.
getUserAccessLevel($user)
loadArchives()
queueLobbyCommand(\@lobbyCommand)
quit($type,$reason,$exitCode=0)
rehost($reason)
slog($message,$level)
This function uses SPADS logging system to write a message in main SPADS log file.
$message
is the log message
$level
is the log level of the message: 0
(critical), 1
(error), 2
(warning), 3
(notice), 4
(info), 5
(debug)
updateSetting($type,$name,$value)
This function updates current SPADS configuration in memory by changing the value of a setting and applying it immediatly. This function does not modify configuration files on disk. The new value provided by the plugin is not checked: the plugin is reponsible for providing only correct values.
$type
is the type of setting to update ("set"
for preset setting, "hSet"
for hosting setting, or "bSet"
for battle setting)
$name
is the name of the setting to update
$value
is the new value of the setting
answer($message)
This function must only be called from a SPADS command handler. It sends a message to the user who issued the command, using the same communication channel that has been used to send the command to SPADS: a private message, a message in battle lobby, a message in game or a message in a lobby chat channel.
broadcastMsg($message)
This function sends a message simultaneously in the battle lobby (if open), in the game (if running) and in the broadcast channels (as configured by the broadcastChannels
global setting).
invalidSyntax($user,$commandName,$cause='')
This function must only be called from a SPADS command handler. It triggers the default SPADS behavior when a user calls a command using invalid syntax, as detailed below:
It answers to the user (using the same communication channel as the one used to call the command) with a message indicating that the command usage is invalid. This message includes a detailed reason if provided as $cause
parameter. If the user is not in game, it also automatically sends the corresponding command help in a private message.
$user
is the user who called the SPADS command
$commandName
is the name of the SPADS command which was called with invalid syntax
$cause
is the detailed reason explaining why the command usage is invalid (optional)
sayBattle($message)
This functions sends a message in the battle lobby (if open).
sayBattleAndGame($message)
This function sends a message simultaneously in the battle lobby (if open) and in the game (if running).
sayBattleUser($user,$message)
This function sends a message in the battle lobby (if open) to a specific user: only this user will receive the message, but for this user the message will appear in the battle lobby instead of being a private chat message.
sayChan($channel,$message)
This functions sends a message in a specific lobby chat channel (if already joined by SPADS).
sayGame($message)
This functions sends a message in the game (if running).
sayPrivate($user,$message)
This function sends a private message to a user.
getDirModifTime($directory)
secToDayAge($seconds)
secToTime($seconds)
formatArray
formatFloat($float)
formatInteger($integer)
formatList
createDetachedProcess($applicationPath,\@commandParams,$workingDirectory,$createNewConsole)
This function allows plugins to create a new detached/daemon process, which can keep running even if the main SPADS process exits. It returns 1
if the new process has correctly been created, 0
else.
$applicationPath
is the absolute path of the application that will be executed in the detached process.
\@commandParams
is a reference to an array containing the parameters passed to the application.
$workingDirectory
is the working directory for the detached process.
$createNewConsole
indicates if a console must be created for the detached process: 0
means no console is created for the process (daemon mode) 1
means a new console will be created for the detached process (this mode is only available on Windows system)
forkProcess(\&processFunction,\&endProcessCallback,$preventQueuing=1)
This function allows plugins to fork a process from main SPADS process, for parallel processing. In scalar context it returns the PID of the forked process on success, -1
if the fork request has been queued, or 0
if the fork request failed. In list context it returns the PID as first parameter and a handle as second parameter. This handle can be passed as parameter to the removeProcessCallback
function to remove the endProcessCallback
callback.
Note: this function cannot be used by Python plugins on Windows system (refer to section PYTHON SPECIFIC NOTES - Windows limitations for details).
\&processFunction
is a reference to a function containing the code to be executed in the forked process (no parameter is passed to this function). This function can call exit
to end the forked process with a specific exit code. If it returns without calling exit, then the exit code 0
will be used.
\&endProcessCallback
is a reference to a function containing the code to be executed in main SPADS process, once the forked process exited. Following parameters are passed to this function: $exitCode
(exit code of the forked process), $signalNb
(signal number responsible for forked process termination if any), $hasCoreDump
(boolean flag indicating if a core dump occured in the forked process), $pid
(PID of the forked process that just exited).
$preventQueuing
is an optional boolean parameter (default value: 1) indicating if the fork request must not be queued (i.e., the fork request will fail instead of being queued if too many forked processes are already running)
forkCall(\&processFunction,\&endProcessCallback,$preventQueuing=0)
This function allows plugins to call a function asynchronously and retrieve the data returned by this function (this is done internally by forking a process to execute the function and use a socketpair to transmit the result back to the parent process). In scalar context it returns the PID of the forked process on success, -1
if the fork request has been queued, or 0
on error. In list context it returns the PID as first parameter and a handle as second parameter. This handle can be passed as parameter to the removeProcessCallback
function to remove the endProcessCallback
callback.
Note: this function cannot be used by Python plugins on Windows system (refer to section PYTHON SPECIFIC NOTES - Windows limitations for details).
\&processFunction
is a reference to a function containing the code to be executed in the forked process (no parameter is passed to this function). This function must not call exit
, it should use return
instead to return values (scalars, arrays, hashes...) that will be passed to the callback.
\&endProcessCallback
is a reference to a function containing the code to be executed in main SPADS process, once the forked function call (\&processFunction
) returned. The values returned by the forked function call will be passed as parameters to this callback.
$preventQueuing
is an optional boolean parameter (default value: 0) indicating if the fork request must not be queued (i.e., the fork request will fail instead of being queued if too many forked processes are already running)
removeProcessCallback($processHandle)
This function can be used by plugins to remove the callbacks on forked processes added beforehand with the forkProcess
and forkCall
functions, if the callback hasn't been called yet (i.e. the corresponding forked process didn't exit yet). It returns 1
if the callback could be removed, 0
else.
$processHandle
is an internal process handle, returned as second return value by the forkProcess
and forkCall
functions.
addTimer($name,$delay,$interval,\&callback)
This function allows plugins to add timed events (timers) in order to delay and/or repeat code execution. It returns 1
if the timer has correctly been added, 0
else.
$name
is a unique name given by the plugin for this timer.
$delay
is the delay in seconds before executing the \&callback
function.
$interval
is the interval in seconds between each execution of the \&callback
function. If this value is set to 0, the \&callback
function will be executed only once.
\&callback
is a reference to a function containing the code to be executed when the timed event occurs. This callback must not be blocking, otherwise SPADS may become unstable.
removeTimer($name)
This function must be used by plugins to remove timed events (timers) added previously with the addTimer
function. It returns 1
if the timer could be removed, 0
else. Note: Non-repeating timers (i.e. having null interval value) are automatically removed once they are triggered.
$name
is the unique timer name given by the plugin when the timer was added using the addTimer
function.
addSocket(\$socketObject,\&readCallback)
This function allows plugins to add sockets to SPADS asynchronous network system. It returns 1
if the socket has correctly been added, 0
else.
Note: this function cannot be used by Python plugins on Windows system (refer to section PYTHON SPECIFIC NOTES - Windows limitations for details).
\$socketObject
is a reference to a socket object created by the plugin
\&readCallback
is a reference to a plugin function containing the code to read the data received on the socket. This function will be called automatically every time data are received on the socket, with the socket object as unique parameter. It must not block, and only unbuffered functions must be used to read data from the socket (sysread()
or recv()
for example).
removeSocket(\$socketObject)
This function allows plugins to remove sockets from SPADS asynchronous network system. It returns 1
if the socket has correctly been removed, 0
else.
\$socketObject
is a reference to a socket object previously added by the plugin
fix_string(spads_string[,...])
This function allows Python plugins to automatically convert byte strings to normal strings if needed. The function takes any number of byte strings or normal strings as parameters, and returns them converted to normal strings if needed (parameters which are already normal strings are returned without any modification). Refer to section PYTHON SPECIFIC NOTES - Perl strings conversions for the use case of this function. Here is an example of usage:
import perl
spads=perl.ExamplePlugin
[...]
class ExamplePlugin:
[...]
def onPrivateMsg(self,userName,message):
(userName,message)=spads.fix_string(userName,message)
[...]
def hMyCommand(source,user,params,checkOnly):
user=spads.fix_string(user)
for i in range(len(params)):
params[i]=spads.fix_string(params[i])
get_flag(flag_name)
This function allows Python plugins to retrieve indicators (boolean flags) regarding the behavior of the plugin API and the availability of functionalities on current system.
Currently 3 flags are supported:
can_add_socket
: indicates if the addSocket
function of the plugin API is available from Python plugin on this system
can_fork
: indicates if the fork functions of the plugin API (forkProcess
and forkCall
) are available from Python plugins on this system
use_byte_string
: indicates if the strings passed as parameters to Python plugin callbacks on this system are Python byte strings or normal Python strings
Here is an example of usage:
import perl
spads=perl.ExamplePlugin
[...]
if spads.get_flag('can_add_socket'):
spads.addSocket(socket,readSocketCallback)
else:
spads.slog("This plugin requires the addSocket function",1)
return False
Following constants are directly accessible from Perl plugin modules (accessible via perl.eval('$::SpadsPluginApi::...')
from Python plugin modules):
$spadsVersion
$spadsDir
Following variables are directly accessible from Perl plugin modules (accessible via perl.eval('...')
from Python plugin modules), but it is strongly recommended to use the accessors from the API instead:
$::autohost
%::conf
%::confMacros
%::currentVote
$::lobby
$::lobbyState
$::p_runningBattle
%::plugins
@::pluginsOrder
$::spads
%::spadsCmdHandlers
$::springPid
$::springServerType
%::timestamps
%::bosses
SPADS plugin development tutorials (Perl)
SPADS plugin development tutorials (Python)
Commented SPADS plugin templates (Perl): Simple plugin, Configurable plugin, New command plugin
Commented SPADS plugin templates (Python): Simple plugin, Configurable plugin, New command plugin
SPADS documentation, especially regarding plugins management: pluginsDir setting, autoLoadPlugins setting, plugin command
Spring lobby protocol specifications
Spring autohost protocol specifications (from source comments)
Inline::Python Perl module (the bridge between Perl and Python): documentation from meta::cpan, GitHub repository
Copyright (C) 2013-2024 Yann Riou <yaribzh@gmail.com>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.