Those of you who idle in #srb2fun will probably know what I'm about to show here. A while ago I was fiddling with the Twitter API, and found it to be rather nice and simple. My next train of thought was: "Something like this for SRB2 and other servers would be neat..."
So, during some free time at college, I decided to crack open my Ubuntu PHP Editor of choice and begin work on a snazzy little wrapper for servers. After reminding myself of classes (why have I not been using them more?) and fiddling with PHP's process controls, I was able to get both SRB2 and Minecraft to receive input from a PHP script which starts their server binaries in the first place. Not content, I added in a basic web server. Yes, the scripting language primarily used with web servers can also be its own web server.
After a nice bit of sprucing, I now have a fully modular API for interacting with servers that run from command line. What this means, basically, is that you could either control SRB2 using your browser, or write something that interfaces with the API like a GUI client, or a WebUI. Think of it like RCON for Source games, except it's over HTTP.
At the moment, I still have some work to do on it, I need to secure it down with auth keys so you need the key to push a command, and I have a lot more commands to add, but here's some basics:
Each server module has a PHP file under /includes/servers, so for SRB2, this is simply srb2.php.
The main script, wrapper.php, has a define line for the server to integrate with, as well as the path and the port the web server listens on (I have mine set to 5031 right now).
Simple, right?
Now here's how adding a command works:
That's all there is to it, here's a breakdown of the parameters for that:
"/players/max" is the URL to access the API command, this would be followed by a file extension, at the moment the script will only output JSON and XML (see example below). Since I was testing on localhost, I just do:
...to set the maxplayers to 8.
"command" is the command type, this can either be "command" or "function", the former will send a command to the SRB2 console, while function will execute a PHP function within the GameServer (srb2.php) class.
"maxplayers" is the command to process, since this is a command type, it will pass maxplayers followed by the arguments to the SRB2 console.
array('number' => $handler->args('', 'int')) is the argument specification. 'number' is the argument that it reads from the URL (?number=8) while the '' is the text that could come before the value in the SRB2 console (you could put -gametype here for a map parameter, since it needs '-gametype match' or similar to work properly) since maxplayers has nothing before the value, this is blank here. 'int' is the value type, maxplayers only takes a numerical value, so the type is set to integer to reflect this. Currently this supports 'int', 'bool' (true/false, for things like -force that don't have a value after the -force) and 'string' (for pretty much anything else, like 'say').
The array argument is optional, so if for example I just need to list players, I wouldn't need an argument for that.
Simples.
Here's an example of the output, using http://localhost:5031/api/info/files.xml which outputs the file list:
That's about it for now, I plan to get the script to start restarting the server on errors, etc. And sooner or later, I'll try and get it into a portable, cross-platform state and release it. I'd like to try and get a library of modules put together, so if anyone's up for lending a hand, or knows of any games that could benefit from this, do tell.
What is the point in this? The API alone isn't very helpful, but when coupled with UIs, both desktop and Web, you have some pretty powerful kit for remotely controlling servers.
I think that's about it in terms of explanation, I probably missed something but I'm sure I'll notice sooner or later.
So, during some free time at college, I decided to crack open my Ubuntu PHP Editor of choice and begin work on a snazzy little wrapper for servers. After reminding myself of classes (why have I not been using them more?) and fiddling with PHP's process controls, I was able to get both SRB2 and Minecraft to receive input from a PHP script which starts their server binaries in the first place. Not content, I added in a basic web server. Yes, the scripting language primarily used with web servers can also be its own web server.
After a nice bit of sprucing, I now have a fully modular API for interacting with servers that run from command line. What this means, basically, is that you could either control SRB2 using your browser, or write something that interfaces with the API like a GUI client, or a WebUI. Think of it like RCON for Source games, except it's over HTTP.
At the moment, I still have some work to do on it, I need to secure it down with auth keys so you need the key to push a command, and I have a lot more commands to add, but here's some basics:
Each server module has a PHP file under /includes/servers, so for SRB2, this is simply srb2.php.
The main script, wrapper.php, has a define line for the server to integrate with, as well as the path and the port the web server listens on (I have mine set to 5031 right now).
Simple, right?
Now here's how adding a command works:
Code:
$handler->addHandler("/players/max", "command", "maxplayers", array('number' => $handler->args('', 'int')));
"/players/max" is the URL to access the API command, this would be followed by a file extension, at the moment the script will only output JSON and XML (see example below). Since I was testing on localhost, I just do:
Code:
http://localhost:5031/api[B]/players/max[/B].json?number=8
"command" is the command type, this can either be "command" or "function", the former will send a command to the SRB2 console, while function will execute a PHP function within the GameServer (srb2.php) class.
"maxplayers" is the command to process, since this is a command type, it will pass maxplayers followed by the arguments to the SRB2 console.
array('number' => $handler->args('', 'int')) is the argument specification. 'number' is the argument that it reads from the URL (?number=8) while the '' is the text that could come before the value in the SRB2 console (you could put -gametype here for a map parameter, since it needs '-gametype match' or similar to work properly) since maxplayers has nothing before the value, this is blank here. 'int' is the value type, maxplayers only takes a numerical value, so the type is set to integer to reflect this. Currently this supports 'int', 'bool' (true/false, for things like -force that don't have a value after the -force) and 'string' (for pretty much anything else, like 'say').
The array argument is optional, so if for example I just need to list players, I wouldn't need an argument for that.
Simples.
Here's an example of the output, using http://localhost:5031/api/info/files.xml which outputs the file list:
Code:
<?xml version="1.0" encoding="UTF-8" ?>
[URL="http://mb.srb2.org/#"]-[/URL] <nodes>
[URL="http://mb.srb2.org/#"]-[/URL] <node>
<status>0</status>
<filesize>76123104</filesize>
<important>1</important>
<filename>srb2.srb</filename>
<md5>1f698dd35bcedb04631568a84a97d72b</md5>
</node>
[URL="http://mb.srb2.org/#"]-[/URL] <node>
<status>0</status>
<filesize>31147127</filesize>
<important>1</important>
<filename>zones.dta</filename>
<md5>86ae3f9179c64358d1c88060e41bd415</md5>
</node>
[URL="http://mb.srb2.org/#"]-[/URL] <node>
<status>1</status>
<filesize>358189</filesize>
<important>1</important>
<filename>sonic.plr</filename>
<md5>f699d4702b9b505db621e5ad5af4f352</md5>
</node>
[URL="http://mb.srb2.org/#"]-[/URL] <node>
<status>1</status>
<filesize>312488</filesize>
<important>1</important>
<filename>tails.plr</filename>
<md5>dfbbc38080485c70a84a57bb734ceee9</md5>
</node>
[URL="http://mb.srb2.org/#"]-[/URL] <node>
<status>1</status>
<filesize>314552</filesize>
<important>1</important>
<filename>knux.plr</filename>
<md5>1ea958e2aee87b6995226a120ba3eaac</md5>
</node>
[URL="http://mb.srb2.org/#"]-[/URL] <node>
<status>1</status>
<filesize>146581</filesize>
<important>1</important>
<filename>rings.wpn</filename>
<md5>8f702416c15060cd3c53c71b91116914</md5>
</node>
[URL="http://mb.srb2.org/#"]-[/URL] <node>
<status>1</status>
<filesize>363104</filesize>
<important>1</important>
<filename>drill.dta</filename>
<md5>6b1cf9b41e41a46ac58606dc6e7c9e05</md5>
</node>
[URL="http://mb.srb2.org/#"]-[/URL] <node>
<status>1</status>
<filesize>175544</filesize>
<important>1</important>
<filename>soar.dta</filename>
<md5>8d080c050ecf03691562aa7b60156fec</md5>
</node>
[URL="http://mb.srb2.org/#"]-[/URL] <node>
<status>0</status>
<filesize>60932141</filesize>
<important>0</important>
<filename>music.dta</filename>
<md5>a01d4bee3a26cb06bd161d7ccd343582</md5>
</node>
</nodes>
What is the point in this? The API alone isn't very helpful, but when coupled with UIs, both desktop and Web, you have some pretty powerful kit for remotely controlling servers.
I think that's about it in terms of explanation, I probably missed something but I'm sure I'll notice sooner or later.