This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
client_side_scripting:client_scripting_interface-basic_howto [2015/11/30 01:51] partmedia Reduce unnecessary verbosity |
client_side_scripting:client_scripting_interface-basic_howto [2019/09/13 13:17] boingman Updated monitor section to include the ncom command in JXClient RC 1.20.0 |
||
---|---|---|---|
Line 8: | Line 8: | ||
===== Getting Started ===== | ===== Getting Started ===== | ||
- | To run a script in the client, use the //script// command, which takes a path to the script to run. 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. | + | 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. |
+ | |||
+ | The ''scripts'' command lists running scripts with a numeric identifier. Scripts can be stopped using the ''scriptkill'' command. The ''scripttell'' command can be used to send arbitrary commands to a script. | ||
==== Hello World ==== | ==== Hello World ==== | ||
- | 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 a language. The script is quite simple: | + | Save the following script in a file, mark it executable, and run it in the client using the ''script'' command: |
- | #include <stdio.h> | + | #!/usr/bin/env python |
- | + | print("issue 1 1 say Hello, world!") | |
- | 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 scripts. That'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. Nice, isn'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. | + | The ''issue'' interface command runs a given command as if a user typed it into the command window. It 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. |
- | ===== 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 86: | Line 59: | ||
| | ||
monitor -1 1 run_stop | monitor -1 1 run_stop | ||
+ | |||
+ | If you are using JXClient Release Candidate 1.12.0 (or older), monitor commands sent to the script will look like: | ||
+ | |||
+ | ncom XXYYYYeast | ||
+ | |||
+ | Where XX is a 16-bit packet ID and YYYY is a 32-bit repeat indicator. Binary data is transmitted in network byte order (big endian). NOTE: Newline characters regularly occur in the packet ID field so reading this line will have to contend with that, simply reading a line will invariably end in error. It is anticipated that this issue will be fixed at some point in the future. | ||
If you type the command __scripts__ in your client you will see our script is still running.\\ | If you type the command __scripts__ in your client you will see our script is still running.\\ | ||
Line 147: | Line 126: | ||
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? ===== | + | |
+ | ===== Reference ===== | ||
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. | 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. | ||
Line 177: | Line 158: | ||
| 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)| | ||
+ | | 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 | | ||
+ | Note: player, skills, spells, stat path were added between versions 1.11 and 1.50 of the client.\\ | ||
</box> | </box> | ||
- | :!: 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. | + | FIXME \\ |
+ | :!: 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.\\ | ||
+ | :!: No, you do not need to watch requests (anymore?). The client will send the request to stdin of the script. | ||
* //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. | ||
Line 248: | Line 236: | ||
FIXME add a complete set of commands that work with <repeat> and another of those that work without it. | FIXME add a complete set of commands that work with <repeat> and another of those that work without it. | ||
- | ===== Windows-specific notes ===== | + | |
+ | ===== Platform-Specific Notes ===== | ||
Scripting works thanks to a patch from archaios. Known issues are: | Scripting works thanks to a patch from archaios. Known issues are: | ||