Dev:Games Plugin Howto
From AMSN
Contents |
Introduction
This tutorial will teach you on how to use the game API of aMSN to develope your own game plugin. First of all you should have read the Dev:Plugin Developer Guide as a prerequisite, especially the basics are required.
First steps
First of all, you need to create the first steps for your own plugin (plugininfo.xml, (de-)init proc, register plugin, ...) so that you can load and unload in within your aMSN. To let aMSN recognize that your plugin is a game plugin, and that it should get listed in the games list, you have to register your plugin/game at the game interface.
::MSNGamesPlugins::register
proc register { name protocolVersion appID triggerProcs }
Parameters:
- name: a unique name for your game plugin
- protocolVersion: the protocol version of the games stack your plugin can use (at the moment it's always 1) in the case it could change one day
- appID: a list of appIDs and their corresponding names; you can, in theory, handle more than one game with one plugin
- triggerProcs: a list of event procs that get called by the games stack
Return value:
- The protocol version the games stack uses. It should be equal to the protocolVersion parameter, just to make sure the games stack doesn't do anything your plugin doesn't understand or the other way round.
An example from the Tic Tac Toe plugin:
proc RegisterGame {} {
set name "tictactoe"
set pVer 1
set appId [list [list "1021" [trans gamettttitle]]]
set funcs [list \
"::GameTTT::onCreate" \
"::GameTTT::onDestroy" \
"::GameTTT::onRestart" \
"::GameTTT::onStart" \
"::GameTTT::onGameEnd" \
"::GameTTT::onMessage" \
]
set ret [::MSNGamesPlugins::register $name $pVer $appId $funcs]
if {$ret != $pVer} {
#oops, seems like plugin has older protocol version or registering was unsuccessful so unregister again
status_log "registering tictactoe was unsuccessful, return code: $ret" red
::MSNGamesPlugins::unregister $name
}
}
::MSNGamesPlugins::unregister
proc unregister { name }
Parameters:
- name: the unique name for your game plugin (the same you used for registering!)
Return value:
- (none)
Make sure to always unregister your game when unloading the plugin, otherwise it will still be available in the games list although the plugin has been unloaded before!
The Events
Registering your game needs you to specify a bunch of procs that get called by the games stack when a game event occurs. They are listed in the order on how they have to be placed in the triggerProcs list:
onCreate
proc onCreate { sid param }
Parameters:
- sid: a session id, identifying a single game session
- param: (not used here)
Return value:
- (none)
Description:
- This event is triggered after one user has invited another user and the other user has accepted the invitation.
- Note: The game doesn't start yet, it usually takes a few seconds, because after that, WLM users have to load the game and have to see the ads before being able to play.
onDestroy
proc onDestroy { sid param }
Parameters:
- sid: a session id, identifying a single game session
- param: (not used here)
Return value:
- (none)
Description:
- This event is triggered after the other user has closed the game session.
- Note: I'm not sure at the moment, but I think this event can also get triggered after the game was closed locally! (TODO: check this!)
- You need to clean up internal storage data (see one of the next topics!) ..
onRestart
proc onRestart { sid param }
Parameters:
- sid: a session id, identifying a single game session
- param: (not used here)
Return value:
- (none)
Description:
- This event is triggered after both players have confirmed to play another round (restart the game).
- Note: This event doesn't replace the onRestart event, it replaces the onCreate event!
onStart
proc onStart { sid param }
Parameters:
- sid: a session id, identifying a single game session
- param: (not used here)
Return value:
- (none)
Description:
- This event is triggered after both users are ready loading their games (or have decided to restart the game) and the communication channel is established.
- Note: This doesn't mean the game can begin now in all cases! The game itself may have an additional handshake mechanism to make sure the other player is ready, but this is the job of the game plugin!
onGameEnd
proc onGameEnd { sid param }
Parameters:
- sid: a session id, identifying a single game session
- param: (not used here)
Return value:
- (none)
Description:
- This event is triggered after a game round is finished and the other player has clicked the restart button.
onMessage
proc onMessage { sid param }
Parameters:
- sid: a session id, identifying a single game session
- param: a message received from the communication channel
Return value:
- (none)
Description:
- This event is triggered after a message has been received from the communication channel.
- Note: Messages consist of the message itself and a channel identifier prepended, seperated by a :, to the message. The channel identifier can be 0 for a "system" message or 18 for the game channel. Usually the event shouldn't receive any "system" messages because the game stack interprets and filters them. So the messages received here usually look like that:
18:this is a test message
(or)
18:-1
Interaction
You already know how to receive messages from the communication channel and how to receive events. Now you need to interact with the other player.
::MSNGamesInterface::send
proc send { sid data }
Parameters:
- sid: the session id of the current game session
- data: the message being sent to the communication channel
Return value:
- (none)
Description:
- You need to prepend the "18:", mentioned in the description of the onMessage event, to identify your message as a normal game message.
::MSNGamesInterface::restartGame
proc restartGame { sid }
Parameters:
- sid: the session id of the current game session
Return value:
- (none)
Description:
- When a game round is finished and the player wants to restart the game, this proc has to be called after the player clicked the restart button.
::MSNGamesInterface::closeGame
proc closeGame { sid }
Parameters:
- sid: the session id of the current game session
Return value:
- (none)
Description:
- This proc has to be called after the player has closed the game (window). The other player receives the message that the player has closed the game.
- Note: The game session is still alive after that call. You still need to call the next proc if you want to finally close the communication channel and clean up the internal memory storage!
::MSNGamesInterface::destroyGame
proc destroyGame { sid }
Parameters:
- sid: the session id of the current game session
Return value:
- (none)
Description:
- This proc closes the communication channel and cleans up all the internal memory storage.
- Note: Make sure calling this proc is the last thing you do within in a session! After calling that proc the session ID gets invalidated, no events get triggered anymore and calling procs with the sid will fail!
Data Storage
Your plugin needs some data storage for sure, for example for storing the game state, scores or similar things. As your plugin can be called several times concurrently, you can't store your game dependent data in a global variable, because it would be valid to *all* running sessions. So you need to store your data in a variable depending on the session. There are two procs that help you managing these variables:
::MSNGamesInterface::setSetting
proc setSetting { sid key value }
Parameters:
- sid: the session id of the current game session
- key: the variable name
- value: the value of the variable
Return value:
- (none)
::MSNGamesInterface::getSetting
proc getSetting { sid key default }
Parameters:
- sid: the session id of the current game session
- key: the variable name
- default: a default value, in the case the variable doesn't exist yet
Return value:
- the value of the stored variable
Predefined variables/variables set by the games stack
There are some variables that get set by the games stack and contain useful information for a plugin:
- opponentnick: the nick of the opponent player
- inviter: 1 = the local player invited the other player, 0 = the local player was invited by the other player
... and some with only internal data, but you shouldn't use them:
- started
- handshakestate
- opponentready

