:: webmod docs : w scripting language ::

:: webmod ::
{w.scripting:language}

I. About
WebMod provides a scripting language preprocessor, that allows you to create dynamic web pages. It supports cookies, GET and POST vars, Half-Life & mods internal data, and say, enough things to let you make great pages...
All scripting parts are included into HTML code between brackets : <html stuff> some text {w script} other <html things>.
The only extension allowed for pages to be parsed is 'w' : page.w, index.w, mylongnamedpage.w ...
This document introduces to some scripting basics, as variables and available operands.
II. Variables
All variables are as follow : X.name -- where X is a letter identifying the type of the var, and name the name of the var in this type.
a. available var types

Type | Full name | Description
W | WebMod var | here go many vars that can not be found anywhere else, among which some server & web client info
c | CVar | server CVars
v | script vars | variables to be used by scripts (specific to each instance of each script)
p | player info | player-specific variables (only used in "player" loops and functions ; see below)
m | map info | map vars (name) (only used in "map" loops ; see below)
t | time & date | current (local server) time and date vars
h | HTTP headers | some header lines that can be sent to the browser
C | cookies | web client's cookies
P | POST vars | data sent by the client browser with POST method -- typically from a HTML form
G | GET vars | data sent by the client browser with GET method -- parameters right after the URL : http://myhost:27015/mypage.w?mode=display

b. webmod vars

Name | R | W | Description
W.maxplayers | X |  | maximum number of players the server can accept
W.map | X | X | current map
W.moddir | X |  | full path to the mod directory (/usr/games/hlds_l/cstrike, C:\HLServer\cstrike, ...)
W.users | X |  | current number of users (connecting + playing clients)
W.players | X |  | current number of players (ingame clients, fully connected)
W.url | X |  | current URL (/, /index.w, ...)
W.clientip | X |  | web client's ip address
W.OS | X |  | game server operating system : Win32, Linux or FreeBSD
W.os | X |  | win32, linux or freebsd

c. cvars
Please note these are just examples ; all cvars are available (read & write of course).

Name | R | W | Description
c.hostname | X | X | server hostname
c.admin_mod_version | X | X | AdminMod version (if installed ; empty string otherwise) (writeable but you'd better not...)
c.sv_gravity | X | X | current gravity (default : 800)
... | X | X | ...

d. script vars
Scripts can read & write their own variables : v.varname ; varname can be any word (max 32 characters).
Maximum length for their values is 512 characters.
Maximum number of vars per script is 256.
e. player info
These vars are only available in "player" type loops and functions (see below). They are read-only.

Name | R | W | Description
p.name | X |  | name :-p
p.authid | X |  | AuthID (WONID or SteamID) (for LAN servers, WONID=4294967295)
p.id | X |  | player ID (1, 2, 3, ..., 'maxplayers')
p.uid | X |  | player UID (1, 2, 3, ...) (this is a counter starting with 1, reset only at server restart ; so it counts connections the server has accepted so far)
p.ctime | X |  | hh:mm:ss - time for which the player has been connected (if not connected : 0)
p.ptime | X |  | hh:mm:ss - time for which the player has been playing (starts when entering the game) (if not ingame : 0)
p.ping | X |  | latency (milliseconds)
p.loss | X |  | network loss
p.ip | X |  | ip address from which the client is playing
p.ingame | X |  | 0 if player is not ingame, 1 otherwise
p.connected | X |  | 0 if player is not connected, 1 otherwise (btw you should never need to use it)

f. map file info
These vars are only available in "map" type loops (see below). They are read-only.

Name | R | W | Description
m.name | X |  | map name !

g. time & date
Read-only vars about local server's time and date.

Name | R | W | Description
t.hour t.min t.sec | X |  | hours, minutes and seconds (2 characters : '1' gives "01")
t.weekday t.day t.month t.year t.year2 | X |  | day of week ("0":sunday ... "6":saturday) day of month ("01"..."31") month of year ("01"..."12") year (4 digits) year (2 digits)
t.weekdayname t.weekdayname2 t.monthname t.monthname2 | X |  | "Sunday" ... "Saturday" "Sun" ... "Sat" "January" ... "December" "Jan" ... "Dec"
t.string | X |  | fully formatted time & date string : Day Mon dd hh:mm:ss yyyy

h. http headers
Here are write-only vars that can be sent to the web browser.

Name | R | W | Description
h.location |  | X | will redirect the browser to another page
h.contenttype |  | X | will change the output's content-type (default : text/html)

i. other http vars
WebMod supports cookies, GET and POST vars. Here are a few examples.

Name | R | W | Description
G.mode | X |  | value passed in the URL : /page.w?mode=display
P.pass | X |  | value from a HTML form : <form action="page.w" method="post"> <input type="password" name="pass"> <input type="submit" value="ok"> </form>

C.cookiename

X

X

client cookie
- 'reading' this will return the value of the cookie sent by the client for this page (in his HTTP request)
- 'writing' will send the cookie to the browser in the HTTP response header
  so if you write to a C.cookie var, then read it, it won't return the value you gave it

III. Scripting syntax
a. generalities
Scripting parts must be enclosed into brackets in order to be parsed by the preprocessor : html{script}html. You can imbricate script blocks within other ones : html{script with some html output{other script}}html.
If you don't want a bracket to be parsed as a script part start, you can escape it like this : \{ (also works with \} and other separators we'll see : \, and \:). It is only required when the character you want to print would normally have some effect in your script ; for example, you don't have to escape } if you are not in a script.
Comments can be added like this : {#blah blah blah}.
Now we'll see which kinds of operands, loops and functions are available.
b. operand ? (test) and associated ones : =, !, >, >=, <, <=, @, &, |
Used to check or to compare vars.

Syntax
{test?what to do/print if TRUE:what to do/print if FALSE}
Example | Description
password : {c.sv_password?yes:no} | prints 'yes' if string identified by 'c.sv_password' (server password cvar) isn't empty, 'no' otherwise
{W.players?some one:no one} playing right now | evaluates W.players (TRUE if non-zero, FALSE otherwise)
{W.players?{W.players} players:no one} on the server right now | eh, our TRUE statement includes a script part !
Want to test more ?
{{c.sv_password=c.rcon_password}? please change your rcon password !} | please note there is no FALSE statement (the ':' separator can be omitted)
{{c.sv_password!c.rcon_password}?: please change your rcon password !} | exactly the same result (no TRUE statement)
Available tests
= ! | strings and integers comparison
> >= < <= | integers comparison

@

searches a string in another one :
{string1@string2} will return/print :
- 0 if string2 does not contain string1
- 2 if string1 first occur in string2 is at the beginning
- 3 if string1 first occur in string2 is at the very end
- 1 if string2 contains string1 anywhere else

& | boolean AND
| | boolean OR

c. operand : (assignment)
Used to assign values to (writeable) vars.

Syntax
{varname:value}
Example | Description
{c.sv_password:hello} | changes the server password
{c.{G.mode}_password:hello} | changes the server or rcon password ; depends on which 'mode' was provided in the URL (page.w?mode=rcon or page.w?mode=sv)
{{P.passfield=c.rcon_password}? {C.rconpass:{P.passfield}}} | sets 'rconpass' cookie to rcon password if good password was entered in a form field named 'passfield' (do nothing otherwise)
{C.rconpass: {{P.passfield=c.rcon_password}? {c.rcon_password}}} | nearly same results ; but clears 'rconpass' cookie if provided password was wrong

d. mathematic operands
You can do simple operations thanks to these : +, -, *, /.
e. functions
Here are a few functions you can use.

Syntax
{@funcname:param1:param2 ...} double @ at the beginning avoids function output
Example | Description
{@@rcon:changelevel de_dust} | sends a command to console ; return value (output) for 'rcon' function is '0' if first parameter was empty, '1' otherwise as we don't want this to be displayed in our html document, we double the '@' character
{@file_exists:{W.moddir}/server.cfg} | displays/returns '1' if file exists (is readable), '0' otherwise
{@@execclient:452:say hello everybody} | sends "say hello everybody" to a player's console, player is identified by his UID (p.uid) ; this function returns/prints 1 if player was found, 0 otherwise (we don't want this to be displayed so we double our '@')
{@trim: some text } | strips blank characters (space, tab, line feed) at the beginning and end of the string : will return/print "some text"
{@player:p.id=7: slot #7 is taken by '{p.name}'} | selects a player by one of his fields (also works with others p. vars) ; the second parameter will be processed as soon as a player verifying the test is found
{@user:p.id=7: slot #7 is taken by '{p.name}'} | same as 'player' function, but also searches in currently connecting players
{@sleep:2} | delays execution for the given amount of seconds
more to come, depending on webmod users needs...

f. loops : L.p (players) and L.u (users)
You can ask WebMod to do something for each player (ingame) / user (ingame or connecting).

Syntax
{L.p:what to do/print}
Example | Description
<ul>{L.p:<li>{p.name}}</ul> | prints (ingame) players names in a dotted list (see above for complete list of player vars)

e. loop : L.m (maps)
Searches for maps.

Syntax
{L.m:what to do/print}
Example | Description
<ul>{L.m:<li>{m.name}}</ul> | prints all maps (.bsp files) in {W.moddir}/maps ; alphabetically sorted

f. loop : L.l (list)
This is kind of a 'for each' loop.

Syntax
{L.l:varname:values,it,will,take:what to do/print}
Example | Description
{L.l:v.myvar:hello,world,!:{v.myvar} } | stupid example ; will print "hello world ! "

g. loop : L.L (list)
Works the same way as L.l but lets you provide the separator (one single character) ; moreover, elements will be extracted after your list is parsed.

Syntax
{L.L:varname:separator:values it will take:what to do/print}
Example | Description
{L.L:v.mapname: :{<<{W.moddir}/mapcycle.txt}: <li>{v.myvar}} | will display each map from your mapcycle.txt (separator is a line feed)

h. loop : L.w (while)
This is a typical 'while' loop.

Syntax
{L.w:test:what to do/print}
Example | Description
{v.i:0} {L.w:v.i<10:hello#{v.i} {v.i:{v.i+1}}} | will display hello#0 hello#1 ... hello#9

i. file read & write
WebMod lets you do (very) basic operations with files. File paths can be relative (to {W.moddir}/addons/w/www), or absolute.

Syntax
{<filename} | reads & parses the file
{<<filename} | reads the file but doesn't parse it
{>filename:content} | overwrites the file with 'content'
{>>filename:content} | appends 'content' to the file
Example | Description
{<includes/head.inc} | reads, parses and displays {W.moddir}/addons/w/www/includes/head.inc
{<<{W.moddir}/server.cfg} | includes {W.moddir}/server.cfg (not parsed)
{>{W.moddir}/mapcycle.txt:de_dust de_dust2} | overwrites mapcycle file ; the server will become a dust 1 & 2 only server !
{>>{W.moddir}/mapcycle.txt:de_rats} | adds de_rats to your server mapcycle

IV. That's all folks !
You might know enough things to build your own scripts and web pages !
Please have a look at WebMod's standard .w pages that use most of these topics we've seen : vars, forms, cookies, functions, loops, file read & write...
Have fun !
-- dJeyL