User Tools

Site Tools


client_side_scripting:client_scripting_interface-basic_howto

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
Next revision Both sides next revision
client_side_scripting:client_scripting_interface-basic_howto [2013/08/23 19:41]
127.0.0.1 external edit
client_side_scripting:client_scripting_interface-basic_howto [2021/04/11 15:07]
partmedia Update documentation for drawextinfo/drawinfo
Line 1: Line 1:
-====== Client Scripting Interface ​- Basic howto ======+====== Client Scripting Interface ======
  
-===== Purpose of this manual ===== +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]]).
-This Howto covers the scripting interface ​present in gtk and x11 client ​under linux and Windows ​(see notes at end).+
  
-===== What is the Client Scripting Interface? ===== +The script ​is started ​from the client ​and communicates by reading information ​from standard input and writing ​commands to standard outputA full list of commands can be found below.
-Basically, the Client Scripting Interface is a way to have an external program (the script) interact client-side with your in-game behaviour. ​The script ​can have a copy of messages sent from the server to your client ​(there is a wide variety of such messages), can have a copy of messages sent from your client to the server (there are also lots of them), may request information (on a item, a map square ...) and finally can issue commands to the serverLets call those actions, respectively,​ server-client spying, client-server spying, examining and interacting.+
  
-===== How do I run my script ===== 
  
-==== C/++, Perl, Python, Bash, and others ​====+===== Before We Begin =====
  
-Remember to ** chmod +x ** the script so that its executable. +Several clients are available for this gameThis page documents ​the scripting capabilities of the GTKv2 client ​and JXClient as of September, 2020. Some information may be missing or outdated.
-In the client ​type   ​** ​  ​script <​pathname> ​   **+
  
-The script should start.+===== 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.
  
-see also: [[#Windows-specific notes]]+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.
  
-==== Java ==== +The ''​scripts''​ command lists running scripts with numeric identifierScripts can be stopped using the ''​scriptkill''​ (or JXClient ''​scriptkillall''​) command. The ''​scripttell''​ command can be used to send arbitrary commands ​to a script.
-If you write you script in Java it gets bit more tricky but no worries its not that hard  +
-We are going to create ​shell script ​that will run our scripts in Java for us.+
  
-     #​!/​bin/​bash +==== Hello World ====
-     cd /​dir/​to/​java.class +
-     java $*+
  
-Remember to chmod +x this script ​so that its executable+Save the following ​script ​in a file, mark it executable, and run it in the client using the ''​script''​ command:
-Now to run your script this is all you have to do is  "​script /​path/​to/​bashScript blah" ​  blah being your .class file - .class and /​path/​to/​bashScript being the executable bash script.+
  
-===== Pipes, stdout, stdin ===== +    #​!/​usr/​bin/​env python 
-(If this section causes you to consider puking by the second linejump to the next section.)+    print("issue 1 1 say Helloworld!"​)
  
-The script is a program which is external to the client. It can be written in a wide range of languages. This can be C, Java, Perl, Python, Bash script, php, anything you can think about. How can this be possible? Let's take a look at what happens when you type "echo hello world" on a shell prompt. Sure it writes on your terminal "hello world"​. And if you are in a graphical shell prompt? It appears in the graphical console! Some process changed your request of writing to screen to a complex process of //get some system font// and //render the line in the specified window at the specified position//. All this because when you ask to "write hello world to screen"​ you ask, really, to "write hello world to the standard output device"​. This standard output device is called stdout. There is also the stdin, which most of the time is your keyboard and stderr, the standard error device being most of the time the same as stdout.\\ ​  +The ''​issue'' interface command runs given command as if user typed it into the command ​windowIt takes 3 arguments: //repeat//, the number ​of times to repeat ​the command ​(typically used for dropping items); //​must_send//​an integer ​either zero or one; and //​command//, ​the command to execute.
-\\  +
-Ok, and now? Now what we use is exactly the same trick as the graphical console. when the client runs a script, it changes the script's stdin and replace the keyboard input with it's own orders (using ​pipe). And it changes the stdout so instead of writing to screen, the script sends data to the client (using another pipe). And this is how any language can be used. Because every language can write to the screen and read from the keyboard! +
- +
-===== First Script ===== +
- +
-Learn to say hello +
- +
-Here we go for the first script. We will do quite simple things. We will ask our character to say "hello world" around. The script will be written in C because we simply need to choose ​language. The script is quite simple: +
- +
-  #include <​stdio.h>​ +
-   +
-  int main() { +
-      puts("​issue 1 1 say Hello world!\n"​);​ +
-  } +
- +
- +
-Name it first.c, compile it and launch it in your command shell: +
- +
-  tchize@Urd:​~$ /​home/​tchize/​script/​first +
-  issue 1 1 say hello world +
- +
-No surprise in the output (notice the \n at the end in source file). Now we are going to run it in the client. Start the client and log in your prefered server. When it's done, type in the following ​command+
- +
-  scripts +
- +
-Client will say you have no running scriptsThat's good. Now type: +
- +
-  script <​path_to_my_first_script>​ +
- +
-where path_to_my_first_script is the location of your first script. For example I typed: +
- +
-  script ​/home/tchize/script/first +
- +
-and you character says hello to the world. Niceisn't it? Now try this yourself with the following script: +
- +
-  int main(){ +
-       ​printf("​issue 1 1 shout hello world!\n"​);​ +
-       ​printf("​issue 1 1 shout I use scripts!\n"​);​ +
-  } +
- +
-Do you get the idea? every printf you make is a command to the client scripting interface. So now let's look at this command. It begins with issue followed by 2 integers. The command __issue__ is part of the interacting of the Client Scripting Interface. It allows a script ​to send any command the player could send. There are lots of them i won't explain here. Just issue the command ​'help commands'​ to get the list. What are those 2 integers? The first one is repeat. It typically ​is used for dropping items, ​but can be used in other cases. The second ​integer, 1 or 0, is must send. If it is //one//, the command ​must be sent, if it is //zero//, command ​may be lost in the client-server process. Most user will set this to 1.+
  
-===== Second Script ===== 
  
-Spy Kids+==== Monitoring ====
  
 What to do next? As you can see, our script doesn'​t wait very long after issuing commands. And it doesn'​t get information from the client at all. In fact it just //hopes// it is really speaking to the client. We are going to write a simple script which will __issue__ a command to the client and then gets the result. We are going to spy!\\ ​ What to do next? As you can see, our script doesn'​t wait very long after issuing commands. And it doesn'​t get information from the client at all. In fact it just //hopes// it is really speaking to the client. We are going to write a simple script which will __issue__ a command to the client and then gets the result. We are going to spy!\\ ​
Line 139: Line 89:
  
   scriptkill <​pathtoscript>​   scriptkill <​pathtoscript>​
 +
 +(The JXClient additionally recognizes partial script names as well as numbers and has an additional command scriptkillall to stop all currently running scripts in one go.)
  
 or or
 +
   scriptkill <​number>​   scriptkill <​number>​
  
Line 176: Line 129:
 Wow! This mean we know when food is low and we can ask our script to invoke restoration (remember the __issue__ command?) when our character'​s food gets below 50! No starvation anymore. Wow! This mean we know when food is low and we can ask our script to invoke restoration (remember the __issue__ command?) when our character'​s food gets below 50! No starvation anymore.
  
-===== What's next? ===== + 
-There are two things you can still do with Script. The first is to request a bit of informations. The client then tells the script what it wants to know. The second thing is triggering an action of the script from client interface. The command scripttell allows player to say something to a script. The script will get the exact command typed by player. See below for command list.+===== Reference ​===== 
 + 
 +There are two things you can still do with scripts. The first is to request a bit of information. The client then tells the script what it wants to know. The second thing is triggering an action of the script from client interface. The command scripttell allows player to say something to a script. The script will get the exact command typed by player. See below for command list.
  
  
Line 184: 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",​ "​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.
 +    * "​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>
Line 206: Line 164:
 | map all | Return all the known map information | | map all | Return all the known map information |
 | map <x> <y> | Return the information about square x,y in the current map (relative to player position)| | map <x> <y> | Return the information about square x,y in the current map (relative to player position)|
-</​box>​+| player ​     | Return the player'​s tag and title | 
 +| skills ​     | Return a list of all skill names, one per line (see also stat xp) | 
 +| spells ​     | Return a list of known spells, one per line | 
 +| stat paths  | Return spell paths: attuned, repelled, denied |
  
-:!: in order to get the result ​of the request into your script'​s stdin you have to "watch request <data type>"​ before you do the request.+Noteplayer, skills, spells, stat path were added between versions 1.11 and 1.50 of the GTK2 client.\\
  
   * //issue <​repeat>​ <​must_send>​ <​command>//​ - send <​command>​ to server on behalf of client. <​repeat>​ is the number of times to execute command <​must_send>​ tells whether or not the command must sent at all cost (1 or 0). <​repeat>​ and <​must_send>​ are optional parameters. See [[#The Issue Command]] for more details.   * //issue <​repeat>​ <​must_send>​ <​command>//​ - send <​command>​ to server on behalf of client. <​repeat>​ is the number of times to execute command <​must_send>​ tells whether or not the command must sent at all cost (1 or 0). <​repeat>​ and <​must_send>​ are optional parameters. See [[#The Issue Command]] for more details.
-  * //issue mark <​tag>//​ - special case of issue command. only gets the command '​mark'​ and a object tag 
-  * //issue lock <new state> <​tag>//​ - special case of issue command. Only gets the command '​lock'​ with 2 parameters 
   * //draw <​color>​ <​text>//​ - draw the following text on client interface with given color. Usefull for debugging and may help you to forget about using the stderr.   * //draw <​color>​ <​text>//​ - draw the following text on client interface with given color. Usefull for debugging and may help you to forget about using the stderr.
   * //monitor// - start monitoring commands send from client to server. Doesn'​t take any parameter. This goes to the script'​s stdin automatically.   * //monitor// - start monitoring commands send from client to server. Doesn'​t take any parameter. This goes to the script'​s stdin automatically.
   * //​unmonitor//​ - stop monitoring commands send from client to server. Doesn'​t take any parameter.   * //​unmonitor//​ - stop monitoring commands send from client to server. Doesn'​t take any parameter.
 +  * Special case ISSUE commands (these are issued without repeat and mustsend arguments):
 +    * //issue apply <​tag>//​ - Applies the object corresponding to <​tag>​.
 +    * //issue take <tag> [<​count>​]//​ - Retrieves the object corresponding to <​tag>​. If <​count>​ is given, it represents how many items to take. By default all items are retrieved.
 +    * //issue drop <tag> [<​count>​]//​ - Discards the object corresponding to <​tag>​. If <​count>​ is given, it represents how many items to drop. By default all items are discarded.
 +    * //issue mark <​tag>//​ - Marks the object corresponding to <​tag>​.
 +    * //issue lock <​newstate>​ <​tag>//​ - Locks or unlocks the object corresponding to <tag> in your inventory depending on the value of <​newstate>​. Valid values are 1 for lock and 0 for unlock.
  
 ==== Information from client ==== ==== Information from client ====
 Here is an incomplete list of information strings send by client to script. Those informations are sent only because the client asked them, except for scripttell. Here is an incomplete list of information strings send by client to script. Those informations are sent only because the client asked them, except for scripttell.
  
-  * //​scripttell <yourname> <​additional data>// - user send special command to this script specifically+  * //​scripttell <scriptnumber> <​additional data>// - user send special command to this script specifically
   * //monitor <​repeat>​ <​must_send>​ <​command>//​   * //monitor <​repeat>​ <​must_send>​ <​command>//​
   * //monitor mark <​tag>//​   * //monitor mark <​tag>//​
Line 231: Line 196:
  
   * FIXME ** NOTE more information strings to be added here, incomplete list **   * FIXME ** NOTE more information strings to be added here, incomplete list **
- 
  
  
 ==== The issue command ==== ==== The issue command ====
-This command has it'​s ​particularities. I'll try to detail all I've encountered so far.+This command has it'​s ​peculiarities.
  
 Usage: Usage:
   issue [<​repeat>​ [<​must_send>​]] <​command>​   issue [<​repeat>​ [<​must_send>​]] <​command>​
  
-  * //<​repeat>//​ - Times the command should be issued. It's an optional numeric parameter. (Doesn'​t always work as expected) +  * //<​repeat>//​ - Times the command should be issued ​(not repeated after it's initial execution). It's an optional numeric parameter. (Doesn'​t always work as expected.
-  * //<​must_send>//​ - May be 1 or 0. If set to 1 the command will always be sent to the server. Otherwise it //may// be discarded under certain circumstances. ​+  * //<​must_send>//​ - May be 1 or 0. If set to 1 the command will always be sent to the server. Otherwise it //may// be discarded under certain circumstances.
  
 The next examples should clarify the use of numeric parameters. The next examples should clarify the use of numeric parameters.
Line 275: Line 239:
   issue 0 0 lookat 2 3   issue 0 0 lookat 2 3
  
-FIXME add a complete set of commands that work with <repeatand another of those that work without it.+  * FIXME Move "​issue ​<cmd<​tag>"​ documentation here, better formatted. 
 + 
 + 
 +===== Platform-Specific Notes =====
  
-===== Windows-specific notes ===== +Known issues are:
-Scripting works thanks to a patch from archaios. ​Known issues are:+
  
     * If you want to run a Perl script for instance, you need to issue 'perl <​script_name.pl>,​ even if .pl is correctly seen as perl script.     * If you want to run a Perl script for instance, you need to issue 'perl <​script_name.pl>,​ even if .pl is correctly seen as perl script.
     * If script doesn'​t output anything, try turning off buffering (in perl $| = 1) or flush your pipe, or add a sleep at end of program. It seems Windows closes pipes at script termination before client gets time to grab output. ​     * If script doesn'​t output anything, try turning off buffering (in perl $| = 1) or flush your pipe, or add a sleep at end of program. It seems Windows closes pipes at script termination before client gets time to grab output. ​
  
 +===== A Few Thanks =====
  
 +Scripting was rendered initially functional with a patch from archaios and is being kept current by GTKv2 client maintainers Partmedia and crowbert, and JXClient maintainer Ragnor.
  
client_side_scripting/client_scripting_interface-basic_howto.txt · Last modified: 2021/06/19 08:12 by boingman