1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="content-type">
<title>Scripting</title>
</head>
<body>
<table cellpadding="2" cellspacing="2" border="0"
style="text-align: left; width: 100%;">
<tbody>
<tr align="center">
<td style="vertical-align: top; width: 250px;" rowspan="1"
colspan="3">[logo here]<br>
<h2>Client Scripting Interface - Basic howto</h2>
</td>
</tr>
<tr>
<td style="vertical-align: top; width: 250px;">
<h3>Purpose of this
manual</h3>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;">This Howto covers the scripting
interface present in gtk and x11 client under linux and Windows (see notes at end). <br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;"><br>
</td>
</tr>
<tr>
<td style="vertical-align: top; width: 250px;">
<h3>What is the Client
Scripting Interface?</h3>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;">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 server to your client (there is a wide variety of
such messages), can have a copy of messages sent from client to server
(there is also lots of them), may request informations (on a item, a
map square ...) and finally can issue commands to the server. Lets call
those actions, respectively, server-client spying, client-server
spying, examining and interacting.<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;"><br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<h3>Pipes, stdout, stdin</h3>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;">If this section make you puke at
second line, jump to next one.<br>
<br>
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 <span
style="font-weight: bold;">stdout</span>. There is also
the <span style="font-weight: bold;">stdin</span>, which most of the
time is your keyboard and <span style="font-weight: bold;">stderr</span>,
the
standard error device being most of the time the same as stdout.<br>
<br>
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 a 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 screen and read from
keyboard!<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;"><br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<h3>First Script</h3>
<h4 style="text-align: left; margin-left: 40px;">learn to say
hello</h4>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;">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:<br>
<table
style="border: 1pt solid black; width: 75%; text-align: left; margin-left: 50px;"
cellpadding="2" cellspacing="2" border="0">
<tbody>
<tr>
<td style="vertical-align: top;">
<pre>int main(){<br> printf("issue 1 1 say hello world\n");<br>}</pre>
</td>
</tr>
</tbody>
</table>
<br>
Name it first.c, compile it and launch it in shell:<br>
<pre>tchize@Urd:~$ /home/tchize/script/first<br><br>issue 1 1 say hello world</pre>
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:<br>
<pre>scripts</pre>
Client will say you have no running scripts. That's good. Now type:<br>
<pre>script <path_to_my_first_script><br></pre>
where path_to_my_first_script is the location of your first script. For
example I typed:<br>
<pre>script /home/tchize/script/first</pre>
and you character says hello to the world. Nice, isn't it? Now try
yourself with the following script:<br>
<table
style="border: 1pt solid black; width: 75%; text-align: left; margin-left: 50px;"
cellpadding="2" cellspacing="2" border="0">
<tbody>
<tr>
<td style="vertical-align: top;">
<pre>int main(){<br> printf("issue 1 1 shout hello world!\n");<br> printf("issue 1 1 shout I use scripts!\n");<br>}</pre>
</td>
</tr>
</tbody>
</table>
<br>
Do you get the idea? every <span style="font-weight: bold;">printf</span>
you make is a command to the client scripting interface. So now let's
look at this command. It begins with <span
style="font-style: italic; text-decoration: underline;">issue</span>
followed by <span
style="font-style: italic; text-decoration: underline;">2 integers</span>.
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 <span
style="font-style: italic; text-decoration: underline;">repeat</span>.
It let you ask server to execute the command several times. The second
integer, 1 or 0, is <span
style="font-style: italic; text-decoration: underline;">must send</span>.
If it is one, the command must be send, if it is zero, command may be
forget in client-server process. Most user will set this to 1.<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;"><br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<h3>Second Script</h3>
<h4 style="text-align: left; margin-left: 40px;">Spy Kids</h4>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;">What to do next? As you can see,
our script don't wait very long after issuing commands. And it doesn't
get informations from the client at all. In fact it just hope it is
really speaking to the client. We are going to write a simple script
which issue a command to the client and then gets the result. We are
going to spy!<br>
Use the following script and run it in client. Ensure you ran the
client in a console or you won't see any result!<br>
<table
style="border: 1pt solid black; width: 75%; text-align: left; margin-left: 50px;"
cellpadding="2" cellspacing="2" border="0">
<tbody>
<tr>
<td style="vertical-align: top;">
<pre>#include <stdio.h><br><br>int main (){<br> char buf[200];<br> int len;<br> printf ("monitor\n");<br> fflush (stdout);<br> for(;;){ <br> len=read(0,buf,200);<br> if(len)<br> write(2,buf,len); <br> else<br> exit(-1);<br> }<br>}</pre>
</td>
</tr>
</tbody>
</table>
<br>
Now move a bit in the game. A few steps are enough! Look at your
console, you should see something like this:<br>
<pre>monitor 0 0 east</pre>
<pre>monitor 0 0 east</pre>
<pre>monitor 0 0 east</pre>
<pre>monitor -1 0 run 7</pre>
<pre>monitor -1 1 run_stop</pre>
If you type the command <span
style="font-style: italic; text-decoration: underline;">scripts</span>
in client you will see our script is still running.<br>
Let's look more closely at the code. We define a character buffer and a
length. We will use the to read what client send to the script. Then
script send to the client the command "<span
style="text-decoration: underline; font-style: italic;">monitor</span>"
(don't forget the \n). This command ask client to give the script a
copy of all commands sent from client to server. Now each time a
command is sent from client to server, the script will get a "<span
style="text-decoration: underline; font-style: italic;">monitor
<command></span>" string.<br>
a strange C command: <br>
<br>
<pre>fflush(stdout)</pre>
<br>
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.<br>
<br>
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.<br>
<br>
Since we asked to monitor all commands from client to server, we get
them. These commands are our move commands and the use the same format
as <span style="text-decoration: underline; font-style: italic;">issue</span>.
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 console:<br>
<pre>monitor 1 1 say hello world</pre>
<br>
So client sends us lines made of <br>
<pre>monitor <repeat> <must_send> <command></pre>
<br>
Now kill the script by typing command <br>
<pre>killscript <pathtoscript></pre>
<br>
Then type scripts to ensure it's stopped. Edit it, comment the line
printf("monitor\n"), compile and run script again. Move and look at
console. You see nothing. The script didn't ask anything so the client
didn't tell him anything. Your script will only gets what he asked for.<br>
<br>
Now use following code:<br>
<table border="0" cellspacing="2" cellpadding="2"
style="border: 1pt solid black; width: 75%; text-align: left; margin-left: 50px;">
<tbody>
<tr>
<td style="vertical-align: top;">
<pre>#include <stdio.h><br><br>int main (){<br> char buf[200];<br> int len;<br> printf ("watch stats\n");<br> fflush (stdout);<br> for(;;){ <br> len=read(0,buf,200);<br> if(len)<br> write(2,buf,len); <br> else<br> exit(-1);<br> }<br>}</pre>
</td>
</tr>
</tbody>
</table>
<br>
This time we are requesting commands sent from server to client. But
there are far more of them. So watch take as argument the begin of all
commands we want to get. Here we want every stat command from client.
And in console we see, when running script:<br>
<pre>watch stats food 398</pre>
<pre>watch stats food 397</pre>
<pre>watch stats food 396</pre>
<pre>watch stats food 395</pre>
<br>
Waw, this mean we know when food is below and we can ask our script to
invoke restoration (remember the issue command?) when below 50
food! No starvation anymore.<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;"><br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<h3>What's next?</h3>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;">There are two things you can
still do with Script. The first is to <span
style="text-decoration: underline; font-style: italic;">request</span>
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 <span
style="font-style: italic; text-decoration: underline;">scripttell</span>
allows player to say something to a script. The script will get the
exact command typed by player. See below for command list.<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;"><br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<h3>Commands to client</h3>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;">Here is a list of command the
script can send to client.<br>
<br>
<span style="font-style: italic; text-decoration: underline;">watch</span>
<command type><br>
<span style="font-style: italic; text-decoration: underline;">unwatch</span>
<command type><br>
<div style="margin-left: 40px;">watch/unwatch the given command
from server-client protocol. <br>
<command type> specify which specify the commands we want to
watch. set to empty to get all commands.<br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">request</span>
<data type><br>
<div style="margin-left: 40px;">Request a piece of informations
from client memory. Following is the
list of<data type> allowed:<br>
<br>
</div>
<table
style="border: 1px solid black; text-align: left; width: 75%; margin-left: 65px;"
border="0" cellspacing="2" cellpadding="2">
<tbody>
<tr>
<td style="vertical-align: top;">range</td>
<td style="vertical-align: top;">Return the type and name
of the currently selected range attack</td>
</tr>
<tr>
<td style="vertical-align: top;">stat <type></td>
<td style="vertical-align: top;">Return the specified stats</td>
</tr>
<tr>
<td style="vertical-align: top;">stat stats</td>
<td style="vertical-align: top;">Return
Str,Con,Dex,Int,Wis,Pow,Cha</td>
</tr>
<tr>
<td style="vertical-align: top;">stat cmbt<br>
</td>
<td style="vertical-align: top;">Return
wc,ac,dam,speed,weapon_sp</td>
</tr>
<tr>
<td style="vertical-align: top;">stat hp</td>
<td style="vertical-align: top;">Return
hp,maxhp,sp,maxsp,grace,maxgrace,food</td>
</tr>
<tr>
<td style="vertical-align: top;">stat xp</td>
<td style="vertical-align: top;">Return level,xp,skill-1
level,skill-1 xp,...</td>
</tr>
<tr>
<td style="vertical-align: top;">stat resists</td>
<td style="vertical-align: top;">Return resistances</td>
</tr>
<tr>
<td style="vertical-align: top;">weight</td>
<td style="vertical-align: top;">Return maxweight, weight</td>
</tr>
<tr>
<td style="vertical-align: top;">flags</td>
<td style="vertical-align: top;">Return flags (fire, run)</td>
</tr>
<tr>
<td style="vertical-align: top;">items inv<br>
</td>
<td style="vertical-align: top;">Return a list of items in
the inventory, one per line</td>
</tr>
<tr>
<td style="vertical-align: top;">items actv</td>
<td style="vertical-align: top;">Return a list of inventory
items that are active, one per line</td>
</tr>
<tr>
<td style="vertical-align: top;">items on<br>
</td>
<td style="vertical-align: top;">Return a list of items
under the player, one per line</td>
</tr>
<tr>
<td style="vertical-align: top;">items cont</td>
<td style="vertical-align: top;">Return a list of items in
the open container, one per line</td>
</tr>
<tr>
<td style="vertical-align: top;">map pos<br>
</td>
<td style="vertical-align: top;">Return the players x,y
within the current map</td>
</tr>
<tr>
<td style="vertical-align: top;">map near</td>
<td style="vertical-align: top;">Return the 3x3 grid of the
map centered on the player</td>
</tr>
<tr>
<td style="vertical-align: top;">map all</td>
<td style="vertical-align: top;">Return all the known map
information</td>
</tr>
<tr>
<td style="vertical-align: top;">map <x> <y></td>
<td style="vertical-align: top;"> Return the information
about square x,y in the current map</td>
</tr>
</tbody>
</table>
<div style="margin-left: 40px;"> <br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">issue</span>
<repeat> <must_send> <command><br>
<div style="margin-left: 40px;">send <command> to server on
behalf of client. <br>
<repeat> is the number of times to execute command<br>
<must_send> tells wether or not the command must sent at all cost
(1 or 0)<br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">issue</span>
mark <tag><br>
<div style="margin-left: 40px;">special case of issue command.
only gets the command 'mark' and a
object tag<br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">issue</span>
lock <new state> <tag><br>
<div style="margin-left: 40px;">special case of issue command.
Only gets the command 'lock' with 2
parameters<br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">draw</span>
<color> <text> <br>
<div style="margin-left: 40px;">draw the following text on client
interface with given color. Usefull
for debugging and may help you to forget about using the <span
style="font-weight: bold;">stderr</span><br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">monitor</span><br>
<span style="font-style: italic; text-decoration: underline;">unmonitor</span><br>
<div style="margin-left: 40px;">start/stop monitoring commands
send from client to server. Doesn't take
any parameter.<br>
</div>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;"><br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<h3>Informations from client</h3>
</td>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top;">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 <span
style="font-style: italic; text-decoration: underline;">scripttell</span>.
<br>
<br>
<span style="font-style: italic; text-decoration: underline;">scripttell</span>
<yourname> <additional datas><br>
<div style="margin-left: 40px;">user send special command to this
script specifically<br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">monitor</span>
<repeat> <must_send> <command><br>
<span style="font-style: italic; text-decoration: underline;">monitor</span>
mark <tag><br>
<span style="font-style: italic; text-decoration: underline;">monitor</span>
lock <new state> <tag><br>
<div style="margin-left: 40px;">If monitor is on, <command>
is a command send to server by the
client with given repeat. mark and lock are special cases.<br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">watch</span>
<command> <datas> <br>
<div style="margin-left: 40px;">You have put a watch on command
or a part of command (like A to watch
for AddMe command). This command was send by server and your are
notified of it. Content of <data> vary on command and maybe very
complex<br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">request
map</span> <x> <y> <darkness>
<need_update> <have_darkness> <need_resmooth>
<cleared> smooth <face_bottom> <face_middle>
<face_top> heads <face_bottom> <face_middle>
<face_top> tails <face_bottom> <face_middle>
<face_top>\n",<br>
<div style="margin-left: 40px;">Bunch of informations about
square <x>,<y><br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">request
map</span> <x> <y> unknown<br>
<div style="margin-left: 40px;">error occured.<br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">request
map</span> pos <x> <y><br>
<div style="margin-left: 40px;">Tells script current position of
player<br>
</div>
<br>
<span style="font-style: italic; text-decoration: underline;">request
map</span> end<br>
<div style="margin-left: 40px;">Marks the end of a complete map
transfer from client to script. Helpful.<br>
</div>
<br>
<br>
** NOTE more command to be added here, incomplete liste **<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;"><br>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;"><br>
</td>
</tr>
<tr>
<td style="vertical-align: top; width: 250px;">
<h3>Windows-specific notes</h3>
</td>
<td style="vertical-align: top; width: 20px;"><br>
</td>
<td style="vertical-align: top;">
Scripting works thanks to a patch from archaios. Known issues are:
<ul>
<li>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.
<li>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.
</ul>
</td>
</tbody>
</table>
<br>
<br>
</body>
</html>
|