This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
client_side_scripting:client_scripting_interface-basic_howto [2021/04/07 05:55] boingman Grammar. |
client_side_scripting:client_scripting_interface-basic_howto [2021/06/19 08:12] boingman [Using Scripts in the Client] Add further information about JXClient script management. |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Client Scripting Interface ====== | ====== Client Scripting Interface ====== | ||
- | |||
The **client scripting interface** can be used to control a Crossfire client using an external program (//script//). This interface can be used to extend the client or automate repetitive tasks (see [[client_side_scripting:scripts|sample scripts]]). | The **client scripting interface** can be used to control a Crossfire client using an external program (//script//). This interface can be used to extend the client or automate repetitive tasks (see [[client_side_scripting:scripts|sample scripts]]). | ||
- | The script is started from the client and communicates by reading information from standard input and writing commands to standard output. A full list of commands can be found below. | + | The script communicates with the client by reading information from standard input and writing commands to standard output. Scripts can be written in any programming language. The same client scripting interface is used by the GTKv2 client and the JXClient. Any discrepancy should be reported as a bug. |
- | + | ||
- | + | ||
- | ===== Before We Begin ===== | + | |
- | + | ||
- | Several clients are available for this game. This page documents the scripting capabilities of the GTKv2 client and JXClient as of September, 2020. Some information may be missing or outdated. | + | |
- | + | ||
- | ===== Getting Started ===== | + | |
- | The ''script'' command starts a script at the given path. The script must be executable (''chmod +x'' with an appropriate shebang). For some languages, it may be necessary to write a wrapper script to execute the actual program. | + | ===== Using Scripts in the Client ==== |
+ | Several client commands are available to start, stop, list, and communicate with scripts: | ||
- | Additionally, on Windows systems where the shebang is not supported, the player must provide a means of running such a script. For example ''script python <path-to-script>'' if you are using python. | + | * ''script <path>'': start a script located at <path>. |
+ | * ''scripts'': list currently running scripts, along with their numerical IDs | ||
+ | * ''scripttell <id> <string>'': send text to currently running script <id> | ||
+ | * ''scriptkill <id>'': stop currently running script <id> | ||
- | The ''scripts'' command lists running scripts with a numeric identifier. Scripts can be stopped using the ''scriptkill'' (or JXClient ''scriptkillall'') command. The ''scripttell'' command can be used to send arbitrary commands to a script. | + | * JXClient only: |
+ | * ''scriptkillall'': stop all currently running scripts | ||
+ | * Unique alphanumeric substrings of <path> may be used as <id> so that script names may be used in lieu of numbers | ||
+ | ===== Writing Scripts ===== | ||
+ | The script must be executable (e.g. ''chmod +x'' with an appropriate shebang). For some languages, it may be necessary to write a wrapper script to start the program. Additionally, on Windows systems where the shebang is not supported, the player must provide a means of running such a script. For example ''script python <path-to-script>'' if you are using python. | ||
==== Hello World ==== | ==== Hello World ==== | ||
Line 74: | Line 74: | ||
fflush(stdout) | fflush(stdout) | ||
- | The stdout has something called a buffer. When you write to output device, it's not immediatly sent to it. For performance reasons, successive print to stdout are grouped. Most of the time, \n is enough to force sending of data, but we ensure all data are sent to client by flushing the stdout (force empty buffer). In the future, when you think client didn't get a command but the script did send it, ensure you flushed stdout.\\ | + | The stdout has something called a buffer. When you write to output device, it's not immediately sent to it. For performance reasons, successive print to stdout are grouped. Most of the time, \n is enough to force sending of data, but we ensure all data are sent to client by flushing the stdout (force empty buffer). In the future, when you think client didn't get a command but the script did send it, ensure you flushed stdout.\\ |
\\ | \\ | ||
- | Then comes a loop. This loop will read from stdin (where client puts informations for the script) and copy them to stderr (our only access to console since stdout is a connection to client). Because I don't want to use scanf I used the binary read and write commands. Stdin is the file handle 0 and stderr is file handle 2. We first read up to 200 char from stdin and if we read something we write it to stderr. If we didn't read anything, that means we have lost the client (shouldn't happen) and we simply exit. | + | Then comes a loop. This loop will read from stdin (where client puts information for the script) and copy them to stderr (our only access to console since stdout is a connection to client). Because I don't want to use scanf I used the binary read and write commands. Stdin is the file handle 0 and stderr is file handle 2. We first read up to 200 char from stdin and if we read something we write it to stderr. If we didn't read anything, that means we have lost the client (shouldn't happen) and we simply exit. |
Since we asked to monitor all commands from client to server, we get them. These commands are our move commands and they use the same format as issue. If you run our first script while this second script is still running, you will still say hello world, but you'll get the following in your console: | Since we asked to monitor all commands from client to server, we get them. These commands are our move commands and they use the same format as issue. If you run our first script while this second script is still running, you will still say hello world, but you'll get the following in your console: | ||
Line 139: | Line 139: | ||
* //watch <command type>// - watch the given command from server-client protocol. <command type> specifies the commands we want to watch. Set to empty to get all commands. | * //watch <command type>// - watch the given command from server-client protocol. <command type> specifies the commands we want to watch. Set to empty to get all commands. | ||
- | * Besides what is already documented, watch also supports "tick", "drawinfo" (GTK2 client) and "drawextinfo" (JXClient). | + | * Besides what is already documented, watch also supports "tick", "drawextinfo" (for most servers), and "drawinfo" (for very old servers) |
* The "tick" argument will provide the script with "watch tick <integer>", as a tick of the server's clock. | * The "tick" argument will provide the script with "watch tick <integer>", as a tick of the server's clock. | ||
- | * The "drawinfo" and "drawextinfo" arguments are functionally equivalent in the GTK2 client and the JXClient with some minor differences. Both will provide the script with text printed in the Messages text area: The GTKv2 client must receive "watch drawinfo" whereas JXClient must receive "watch drawextinfo". The GTK2 then provides the script with "watch drawinfo <integer> <message>", while the JXClient provides "watch drawextinfo <integer> <integer> <message>". | + | * "drawextinfo" provide the script with text printed in the Messages text area. The format is "watch drawextinfo <integer> <integer> <message>". For some very old servers (none of them which are online at the time of writing), "drawextinfo" is not supported and you must fall back to "drawinfo", which has the arguments "watch drawinfo <integer> <message>". |
* //unwatch <command type>// - unwatch the given command from server-client protocol. <command type> specifies the commands we want to watch. Set to empty to get all commands. | * //unwatch <command type>// - unwatch the given command from server-client protocol. <command type> specifies the commands we want to watch. Set to empty to get all commands. | ||
- | * //request <data type>// - Request a piece of informations from client memory. Following is a table of <data type> allowed: | + | * //request <data type>// - Request a piece of information from client memory. Following is a table of <data type> allowed: |
<box round | Data Type Table> | <box round | Data Type Table> |