Compare commits

...

5 Commits

Author SHA1 Message Date
rarkenin 92bcb90134 Update README.md 2013-03-07 18:48:19 -05:00
Robert Arkenin 8623ecc4a0 Initial commit 2013-03-07 18:41:55 -05:00
Robert Arkenin cdf753c912 Continued work on network protocol; can now handle the headers and magic numbers 2013-02-08 14:49:00 -05:00
Robert Arkenin 74bbd688a9 Begin file work 2013-02-06 20:50:35 -05:00
Robert Arkenin 00f08efbbf Giant restructuring 2013-02-06 20:15:40 -05:00
15 changed files with 998 additions and 10 deletions

View File

@ -1,6 +1,9 @@
minetest-bot-php
A bot for Minetest servers.
================
Licensed under the GNU GPL 3.0.
Please use this bot for beneficial purposes. If this bot is used for griefing, I may not be inclined to maintain it more.
@ -15,3 +18,6 @@ MySQL 5.5 or higher
A non-Windows OS.
A stable internet connection.
Wireshark and an installation of Minetest in case something goes wrong.
Limitations:
It does not work yet!

View File

@ -0,0 +1,27 @@
<?php
$legacyContentTypes = array(
"CONTENT_GRASS"=>1,
"CONTENT_TREE"=>4,
"CONTENT_LEAVES"=>5,
"CONTENT_GRASS_FOOTSTEPS"=>6,
"CONTENT_MESE"=>7,
"CONTENT_MUD"=>8,
"CONTENT_CLOUD"=>10,
"CONTENT_COALSTONE"=>11,
"CONTENT_WOOD"=>12,
"CONTENT_SAND"=>13,
"CONTENT_COBBLE"=>18,
"CONTENT_STEEL"=>19,
"CONTENT_GLASS"=>20,
"CONTENT_MOSSYCOBBLE"=>22,
"CONTENT_GRAVEL"=>23,
"CONTENT_SANDSTONE"=>24,
"CONTENT_CACTUS"=>25,
"CONTENT_BRICK"=>26,
"CONTENT_CLAY"=>27,
"CONTENT_PAPYRUS"=>28,
"CONTENT_BOOKSHELF"=>29,
);
?>

View File

@ -1,15 +1,62 @@
<?php
$nodes=array();
ini_set('memory_limit', '1024M');
$nodes[0][0][0]="CONTENT_IGNORE";//Initialize array, overwritten later anyway.
require_once 'servercommands.php';
require_once 'miscdefines.php';
require_once 'hardwiredContentTypes.php';
require_once 'network.php';
require_once 'processCommunication.php';
require_once 'packet.php';
require_once 'serialize.php';
require_once 'lowLevelNet.php';
require_once 'networkMaintenance.php';
require_once 'sendComm.php';
var_dump(unpack("n",serializeU16(65500)));
var_dump(unpack('n', "\xff\xdc"));
define("CMDTOSERVER", 1);
define("CMDSENDRELIABLE", 2);
define("CMDACKNEEDED", 4);
define("CMDACTIONRELIABLE",8);
class MTBotcommand {
public static $byte;
public static $direction;
public static $ackCommand;
public static $unpackString;
require_once 'knownMap.php';
//define("CMDTOSERVER", 1); //Otherwise to client
//define("CMDSENDRELIABLE", 2);
//define("CMDACKNEEDED", 4);
//define("CMDACTIONRELIABLE", 8);
if (PHP_SAPI != "cli") {
die("Main [FATAL]:Must be run in CLI mode!");
}
if ($argc != 6) {
var_dump($argv);
var_dump($argc);
die("Main [FATAL]:Improper arguments!\r\n Usage: minetestbot.php <host> <port> <username> <pass> <controlfile>");
}
$serverIp = $argv[1];
$serverPort = $argv[2];
$username = $argv[3];
$password = $argv[4];
$controlFile = $argv[5];
$serverSocket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if (false == (socket_connect($serverSocket, $serverIp, $serverPort))) {
die("Connect [FATAL]:Connect failed: reason: " . socket_strerror(socket_last_error($serverSocket)) . "\n");
}
socket_set_nonblock($serverSocket);
//socket_write($serverSocket, "FOOBARFOOBAR");
require_once $controlFile;
//$controlHandle = fopen($controlFile, "rb");
//$fileReadBuffer = fread($controlHandle, 8);
//if (strcasecmp($fileReadBuffer, "mtbotpurephp")!=0){
// die("File [FATAL]:Impropper file header, perhaps not a MTBot control file?");
//}
////TODO: Get password from file
sendTOSERVER_INIT($username, $password);
//$connectSeqNum = sendPacket(FormReliablePacket(FormOriginalPacket("")));
//blockingLoopWaitPacketAck($connectSeqNum);
//while($ourPeerId==0){
// readNetworkPacket($serverSocket);
//}
while(true){
usleep(100);
readNetworkPacket($serverSocket);
}
?>

5
src/knownMap.php Normal file
View File

@ -0,0 +1,5 @@
<?php
?>

7
src/lowLevelNet.php Normal file
View File

@ -0,0 +1,7 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
?>

28
src/miscdefines.php Normal file
View File

@ -0,0 +1,28 @@
<?php
define("MINETEST_MAGIC_NUMBER","\x4f\x45\x74\x03");
define("SER_FMT_VER_INVALID", 255);
// Highest supported serialization version
define("SER_FMT_VER_HIGHEST", 25);
// Lowest supported serialization version
define("SER_FMT_VER_LOWEST", 0);
define("LATEST_PROTOCOL_VERSION", 16);
// Server's supported network protocol range
define("SERVER_PROTOCOL_VERSION_MIN", 13);
define("SERVER_PROTOCOL_VERSION_MAX", LATEST_PROTOCOL_VERSION);
// Client's supported network protocol range
define("CLIENT_PROTOCOL_VERSION_MIN", 13);
define("CLIENT_PROTOCOL_VERSION_MAX", LATEST_PROTOCOL_VERSION);
// Constant that differentiates the protocol from random data and other protocols
define("PROTOCOL_ID", 0x4f457403);
define("PASSWORD_SIZE", 28);
// Maximum password length. Allows for
// base64-encoded SHA-1 (27+\0).
define("IACTION_MOVE", 0);
define("IACTION_DROP", 1);
define("IACTION_CRAFT", 2);
?>

164
src/network.php Normal file
View File

@ -0,0 +1,164 @@
<?php
$packetBuffer = array();
//require_once 'index.php';
define("BASE_HEADER_SIZE", 7);
define("PEER_ID_INEXISTENT", 0);
define("PEER_ID_SERVER", 1);
define("CHANNEL_COUNT", 3);
define("TYPE_CONTROL", 0);
define("CONTROLTYPE_ACK", 0);
define("CONTROLTYPE_SET_PEER_ID", 1);
define("CONTROLTYPE_PING", 2);
define("CONTROLTYPE_DISCO", 3);
define("TYPE_SPLIT", 2);
define("TYPE_RELIABLE", 3);
define("RELIABLE_HEADER_SIZE", 3);
define("SEQNUM_INITIAL", 65500);
$seqnumOut = SEQNUM_INITIAL;
$seqnumIn = SEQNUM_INITIAL;
$ourPeerId = PEER_ID_INEXISTENT;
$serverPeerId = PEER_ID_SERVER;
$bufferedPackets = array();
function readNetworkPacket($socket) {
global $seqnumIn;
global $seqnumOut;
global $ourPeerId;
global $serverPeerId;
global $bufferedPackets;
global $packetsAwaitingSend;
$packet = socket_read($socket, 4096, PHP_BINARY_READ);
if (strlen($packet) > 0) {
echo 'Got packet!';
$protocolId = substr($packet, 0, 4);
$senderPeerId = deserializeU16(substr($packet, 4, 2));
$channel = ord(substr($packet, 6, 1));
$packetType = ord(substr($packet, 7, 1));
switch ($packetType) {
case TYPE_CONTROL:
$controlType = ord(substr($packet, 8, 1));
switch ($controlType) {
case CONTROLTYPE_ACK:
$seqnumAckd = deserializeU16(substr($packet, 9, 2));
unset($packetsAwaitingSend[$seqnumAckd]);
break;
case CONTROLTYPE_SET_PEER_ID:
$peerId = deserializeU16(substr($packet, 9, 1));
$ourPeerId = $peerId;
echo "Got our peer id!";
return true;
break;
case CONTROLTYPE_DISCO:
exit("Disconnected.");
break;
}
break;
case TYPE_RELIABLE:
$incomingSeqnum = deserializeU16(substr($packet, 8, 1));
sendAck($incomingSeqnum);
$packetPayload = substr($packet, 10);
if (isset($bufferedPackets[$seqnumIn])) {
$seqnumIn++;
$seqnumIn = $seqnumIn % 65536;
readNetworkPacket($bufferedPackets[$seqnumIn]);
}
break;
case TYPE_ORIGINAL:
processCommandToClient(substr($packet, 8));
break;
case TYPE_SPLIT:
//TODO Split packet
break;
default:
return false;
break;
}
}
}
function readNetworkPacketNested($packIn) {
global $seqnumIn;
global $seqnumOut;
global $ourPeerId;
global $serverPeerId;
global $packetsAwaitingSend;
global $bufferedPackets;
$packetType = ord(substr($packet, 0, 1));
switch ($packetType) {
case TYPE_CONTROL:
$controlType = ord(substr($packet, 1, 1));
switch ($controlType) {
case CONTROLTYPE_ACK:
$seqnumAckd = deserializeU16(substr($packet, 2, 2));
unset($packetsAwaitingSend[$seqnumAckd]);
case CONTROLTYPE_SET_PEER_ID:
$peerId = deserializeU16(substr($packet, 2, 2));
$ourPeerId = $peerId;
echo "Got our peer ID!";
return true;
break;
case CONTROLTYPE_DISCO:
exit("Disconnected.");
break;
}
break;
case TYPE_RELIABLE:
$incomingSeqnum = deserializeU16(substr($packet, 1, 1));
sendAck($incomingSeqnum);
$packetPayload = substr($packet, 3);
if (isset($bufferedPackets[$seqnumIn])) {
$seqnumIn++;
$seqnumIn = $seqnumIn % 65536;
readNetworkPacketNested($bufferedPackets[$seqnumIn]);
}
break;
case TYPE_ORIGINAL:
processCommandToClient(substr($packet, 1));
break;
case TYPE_SPLIT:
//TODO Split packet
break;
default:
return false;
break;
}
}
function sendPacket($packet) {
global $serverSocket;
socket_write($serverSocket, "\x4f\x45\x74\x03\x00\x01\x00" . $packet);
}
function formReliablePacket($packet) {
global $seqnumOut;
$packetOut = chr(3) . serializeU16($seqnumOut) . $packet;
$seqnumOut++;
return $packetOut;
}
function formOriginalPacket($packet) {
if(strlen($packet)!=0){
return chr(1) . chr(0) . $packet;
}
else{
return chr(1);
}
}
function sendPing() {
global $serverSocket;
$pingPacket = "\x4f\x45\x74\x03\x00\x01\x00" . chr(TYPE_CONTROL) . chr(CONTROLTYPE_PING);
socket_write($serverSocket, $pingPacket);
}
function sendAck($seqnumToAck) {
global $serverSocket;
$ackpacket = "\x4f\x45\x74\x03\x00\x01\x00" . chr(TYPE_CONTROL) . chr(CONTROLTYPE_ACK) . serializeU16($seqnumToAck);
socket_write($serverSocket, $ackPacket);
}
?>

View File

@ -0,0 +1,15 @@
<?php
$packetsAwaitingSend=array();
$lastSend=microtime(true);
function FiveSecPoll(){
global $lastSend;
global $packetsAwaitingSend;
foreach ($packetsAwaitingSend as $seqnumToSend => $data) {
FormReliablePacketWithSeqnum($seqnum, $data);
}
if ((microtime(true)-$lastSend)>=4){
SendPing();
}
}
//function
?>

17
src/packet.php Normal file
View File

@ -0,0 +1,17 @@
<?php
//require_once 'index.php';
//require_once 'network.php';
//class BufferedPacket{
// global $seqnum;
// global $ourPeerId;
// global $serverPeerId;
// public $isControl;
// public $isFrag;
// public $totalFrags;
// public $fragsReady;
// function __construct($seqnum, $t){}
// function isReady(){
// return $totalFrags==$fragsReady;
// }
//}
?>

View File

@ -0,0 +1,105 @@
<?php
require_once 'servercommands.php';
$testPacket = "\x4f\x45\x74\x03\x00\x00\x00\x01\x00\x10\x19\x72\x61\x72\x6b\x65\x6e\x69\x6e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\x62\x2b\x48\x57\x64\x71\x4a\x34\x38\x36\x47\x49\x73\x32\x47\x4e\x74\x6e\x47\x31\x4c\x64\x4a\x48\x4e\x4d\x00\x00\x0d\x00\x10";
function processCommandToClient($packet) {
global $recommended_send_interval;
global $privsarray;
global $mapseed;
global $playerpos;
global $knownMap;
$headerByte = ord(substr($packet, 0, 1));
$datasize = strlen($packet);
//print $headerByte . "\n";
//print ord(substr($packet, 0, 1));
//print "\n";
print CLIENT_INIT;
switch ($headerByte) {
case CLIENT_INIT:
var_dump(($magicNum), ($senderPeerId), ($packetChannel), $packet);
print("DUMMY!");
sendCmd(SERVER_INIT2, array());
/* TODO: CRITICAL Implement sending SERVER_INIT2 */
switch ($datasize) {
case 2 + 1 + 6 + 8 + 4:
/* TODO: Unpack codes for data... */
}
break;
case CLIENT_ACCESS_DENIED:
die("Connect [FATAL]:Connect failed reason: Access denied");
break;
case CLIENT_REMOVENODE:
$nodepos = deserializeNodePos(substr($packet, 1, 6));
removeNode($nodepos);
break;
case CLIENT_ADDNODE:
$nodepos = deserializeNodePos(substr($packet, 1, 6));
$node = deserializeNode(substr($packet, 7));
addNode($nodepos, $node);
break;
case CLIENT_BLOCKDATA:
/* TODO: CRITICAL FIGURE OUT MapNode::deSerialize in mapNode.cpp, as well as deserialize bulk. */
print("Packet Handling [TODO]: CLIENT_BLOCKDATA received but not processed.\n");
break;
case CLIENT_INVENTORY:
/* TODO: MEDIUM Figure out Inventory serialization!!!
* * void InventoryList::deSerialize(std::istream &is) in inventory.cpp
* void Inventory::deSerialize(std::istream &is) in inventory.cpp */
print("Packet Handling [TODO]: CLIENT_INVENTORY received but not processed.\n");
break;
case CLIENT_CHAT_MESSAGE:
$length = deserializeU16(substr($packet, 1, 2));
$message = minetestWideToNarrow(substr($packet));
processChatMsg($message);
break;
case CLIENT_MOVE_PLAYER:
$playerpos = readV3F100(substr($packet, 1, 12));
break;
case CLIENT_DEATHSCREEN:
print("Player [INFO]: Player died at " . $playerpos . toString() . ".\n");
sendCmd(SERVER_RESPAWN, array());
break;
case CLIENT_PRIVILEGES:
$numPrivs = deserializeU16(substr($packet, 1, 2));
$privsarray = array();
$packetPos = 3;
for ($i = 1; $i <= numPrivs; $i++) {
$thisIterationLength = deserializeU16(substr($packet, $packetPos, 2));
$packetPos+=2;
array_push($privsarray, substr($packet, $packetpos, $thisIterationLength));
$packetPos+=$thisIterationLength;
}
$privs = implode(", ", $privsarray);
print("Player [INFO]: Got privs: $privs\n");
break;
case CLIENT_INVENTORY_FORMSPEC:
$length = deserializeU32(substr($packet, 1, 4));
$invSpec = substr($packet, 5, $length);
break;
case CLIENT_DETACHED_INVENTORY:
$nameLength=deserializeU16(substr($packet, 1, 2));
$invName=substr($packet,3, $nameLength);
$invBody=substr($packet,3+$nameLength);
$detachedInvs[$invName]=deserializeInv($invBody); /* TODO: MEDUIM Deserialize Invs. Doesn't look that hard.
* void InventoryList::deSerialize(std::istream &is) in inventory.cpp
* void Inventory::deSerialize(std::istream &is) in inventory.cpp
*/
break;
case CLIENT_SHOW_FORMSPEC:
print("ServerAction [INFO]: Not showing formspec, ignored.");
break;
}
}
function processChatMsg($message) {
print "received chat message: ".$message . "\n";
}
?>

24
src/sendComm.php Normal file
View File

@ -0,0 +1,24 @@
<?php
require_once 'servercommands.php';
function sendTOSERVER_INIT($username, $passphrase) {
$packetToSend = chr(SERVER_INIT);
$packetToSend.=chr(25);
$packetToSend.=str_pad($username, 20, chr(0), STR_PAD_RIGHT);
if (preg_match("/^[A-Za-z0-9]{27}$/", $passphrase) != 1) {
die("The passphrase must be 27 characters, which may be alphanumeric, with case sensitivity.");
}
$packetToSend.=$passphrase . chr(0) . serializeU16(13) . serializeU16(25);
sendPacket(formReliablePacket(formOriginalPacket("")));
sendPacket(formOriginalPacket($packetToSend));
}
function sendTOSERVER_PLAYERPOS() {
$packet = chr(SERVER_PLAYERPOS);
$packet.=$knownmap->player->pos->getAsV3F100();
}
?>

50
src/serialize.php Normal file
View File

@ -0,0 +1,50 @@
<?php
define("POINTEDTHING_NOTHING", 0);
define("POINTEDTHING_NODE", 1);
define("POINTEDTHING_OBJECT", 2);
function deserializeNodePos($in) {
}
function deserializeNode($in) {
global $knownNodes;
}
function deserializeU16($in) {
$retval = unpack("nout", $in);
return $retval[out];
}
function minetestWideToNarrow($in) {
$out = "";
$length = strlen($in);
for ($i = 1; $i < $length; $i+=2) {
$out = $out . $in[$i];
}
return $out;
}
function serializePointedThing($abovesurface, $undersurface, $type) {
/*
* Undersurface gets punched
* Abovesurface is target for node place
*/
$out = "";
$out = $out . chr(0);
$out.=chr($type);
if ($type == POINTEDTHING_NODE) {
$out = $out . serializeNodePos($undersurface);
$out = $out . serializeNodePos($abovesurface);
}return $out;
}
function serializeU16($in){
$retval=pack("n", $in);
//echo("Serialized $in to $retval");
return $retval;
}
?>

490
src/servercommands.php Normal file
View File

@ -0,0 +1,490 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/ define("CLIENT_INIT",0x10);
/*
Server's reply to TOSERVER_INIT.
Sent second after connected.
[0] u16 TOSERVER_INIT
[2] u8 deployed version
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
[12] u64 map seed (new as of 2011-02-27)
[20] f1000 recommended send interval (in seconds) (new as of 14)
NOTE: The position in here is deprecated; position is
explicitly sent afterwards
*/
define("CLIENT_BLOCKDATA",0x20);
define("CLIENT_ADDNODE",0x21);
define("CLIENT_REMOVENODE",0x22);
define("CLIENT_PLAYERPOS",0x23); // Obsolete
/*
[0] u16 command
// Followed by an arbitary number of these:
// Number is determined from packet length.
[N] u16 peer_id
[N+2] v3s32 position*100
[N+2+12] v3s32 speed*100
[N+2+12+12] s32 pitch*100
[N+2+12+12+4] s32 yaw*100
*/
define("CLIENT_PLAYERINFO",0x24); // Obsolete
/*
[0] u16 command
// Followed by an arbitary number of these:
// Number is determined from packet length.
[N] u16 peer_id
[N] char[20] name
*/
define("CLIENT_OPT_BLOCK_NOT_FOUND",0x25); // Obsolete
define("CLIENT_SECTORMETA",0x26); // Obsolete
/*
[0] u16 command
[2] u8 sector count
[3...] v2s16 pos + sector metadata
*/
define("CLIENT_INVENTORY",0x27);
/*
[0] u16 command
[2] serialized inventory
*/
define("CLIENT_OBJECTDATA",0x28); // Obsolete
/*
Sent as unreliable.
u16 command
u16 number of player positions
for each player:
u16 peer_id
v3s32 position*100
v3s32 speed*100
s32 pitch*100
s32 yaw*100
u16 count of blocks
for each block:
v3s16 blockpos
block objects
*/
define("CLIENT_TIME_OF_DAY",0x29);
/*
u16 command
u16 time (0-23999)
Added in a later version:
f1000 time_speed
*/
// (oops, there is some gap here)
define("CLIENT_CHAT_MESSAGE",0x30);
/*
u16 command
u16 length
wstring message
*/
define("CLIENT_ACTIVE_OBJECT_REMOVE_ADD",0x31);
/*
u16 command
u16 count of removed objects
for all removed objects {
u16 id
}
u16 count of added objects
for all added objects {
u16 id
u8 type
u32 initialization data length
string initialization data
}
*/
define("CLIENT_ACTIVE_OBJECT_MESSAGES",0x32);
/*
u16 command
for all objects
{
u16 id
u16 message length
string message
}
*/
define("CLIENT_HP",0x33);
/*
u16 command
u8 hp
*/
define("CLIENT_MOVE_PLAYER",0x34);
/*
u16 command
v3f1000 player position
f1000 player pitch
f1000 player yaw
*/
define("CLIENT_ACCESS_DENIED",0x35);
/*
u16 command
u16 reason_length
wstring reason
*/
define("CLIENT_PLAYERITEM",0x36); // Obsolete
/*
u16 command
u16 count of player items
for all player items {
u16 peer id
u16 length of serialized item
string serialized item
}
*/
define("CLIENT_DEATHSCREEN",0x37);
/*
u16 command
u8 bool set camera point target
v3f1000 camera point target (to point the death cause or whatever)
*/
define("CLIENT_MEDIA",0x38);
/*
u16 command
u16 total number of texture bunches
u16 index of this bunch
u32 number of files in this bunch
for each file {
u16 length of name
string name
u32 length of data
data
}
u16 length of remote media server url (if applicable)
string url
*/
define("CLIENT_TOOLDEF",0x39);
/*
u16 command
u32 length of the next item
serialized ToolDefManager
*/
define("CLIENT_NODEDEF",0x3a);
/*
u16 command
u32 length of the next item
serialized NodeDefManager
*/
define("CLIENT_CRAFTITEMDEF",0x3b);
/*
u16 command
u32 length of the next item
serialized CraftiItemDefManager
*/
define("CLIENT_ANNOUNCE_MEDIA",0x3c);
/*
u16 command
u32 number of files
for each texture {
u16 length of name
string name
u16 length of sha1_digest
string sha1_digest
}
*/
define("CLIENT_ITEMDEF",0x3d);
/*
u16 command
u32 length of next item
serialized ItemDefManager
*/
define("CLIENT_PLAY_SOUND",0x3f);
/*
u16 command
s32 sound_id
u16 len
u8[len] sound name
s32 gain*1000
u8 type (0=local, 1=positional, 2=object)
s32[3] pos_nodes*10000
u16 object_id
u8 loop (bool)
*/
define("CLIENT_STOP_SOUND",0x40);
/*
u16 command
s32 sound_id
*/
define("CLIENT_PRIVILEGES",0x41);
/*
u16 command
u16 number of privileges
for each privilege
u16 len
u8[len] privilege
*/
define("CLIENT_INVENTORY_FORMSPEC",0x42);
/*
u16 command
u32 len
u8[len] formspec
*/
define("CLIENT_DETACHED_INVENTORY",0x43);
/*
[0] u16 command
u16 len
u8[len] name
[2] serialized inventory
*/
define("CLIENT_SHOW_FORMSPEC",0x44);
/*
[0] u16 command
u32 len
u8[len] formspec
u16 len
u8[len] formname
*/
define("SERVER_INIT",0x10);
/*
Sent first after connected.
[0] u16 TOSERVER_INIT
[2] u8 SER_FMT_VER_HIGHEST
[3] u8[20] player_name
[23] u8[28] password (new in some version)
[51] u16 minimum supported network protocol version (added sometime)
[53] u16 maximum supported network protocol version (added later than the previous one)
*/
define("SERVER_INIT2",0x11);
/*
Sent as an ACK for TOCLIENT_INIT.
After this, the server can send data.
[0] u16 TOSERVER_INIT2
*/
define("SERVER_GETBLOCK",0x20); // Obsolete
define("SERVER_ADDNODE",0x21); // Obsolete
define("SERVER_REMOVENODE",0x22); // Obsolete
define("SERVER_PLAYERPOS",0x23);
/*
[0] u16 command
[2] v3s32 position*100
[2+12] v3s32 speed*100
[2+12+12] s32 pitch*100
[2+12+12+4] s32 yaw*100
[2+12+12+4+4] u32 keyPressed
*/
define("SERVER_GOTBLOCKS",0x24);
/*
[0] u16 command
[2] u8 count
[3] v3s16 pos_0
[3+6] v3s16 pos_1
...
*/
define("SERVER_DELETEDBLOCKS",0x25);
/*
[0] u16 command
[2] u8 count
[3] v3s16 pos_0
[3+6] v3s16 pos_1
...
*/
define("SERVER_ADDNODE_FROM_INVENTORY",0x26); // Obsolete
/*
[0] u16 command
[2] v3s16 pos
[8] u16 i
*/
define("SERVER_CLICK_OBJECT",0x27); // Obsolete
/*
length: 13
[0] u16 command
[2] u8 button (0=left, 1=right)
[3] v3s16 blockpos
[9] s16 id
[11] u16 item
*/
define("SERVER_GROUND_ACTION",0x28); // Obsolete
/*
length: 17
[0] u16 command
[2] u8 action
[3] v3s16 nodepos_undersurface
[9] v3s16 nodepos_abovesurface
[15] u16 item
actions:
0: start digging (from undersurface)
1: place block (to abovesurface)
2: stop digging (all parameters ignored)
3: digging completed
*/
define("SERVER_RELEASE",0x29); // Obsolete
// (oops, there is some gap here)
define("SERVER_SIGNTEXT",0x30); // Old signs, obsolete
/*
u16 command
v3s16 blockpos
s16 id
u16 textlen
textdata
*/
define("SERVER_INVENTORY_ACTION",0x31);
/*
See InventoryAction in inventory.h
*/
define("SERVER_CHAT_MESSAGE",0x32);
/*
u16 command
u16 length
wstring message
*/
define("SERVER_SIGNNODETEXT",0x33); // obsolete
/*
u16 command
v3s16 p
u16 textlen
textdata
*/
define("SERVER_CLICK_ACTIVEOBJECT",0x34); // Obsolete
/*
length: 7
[0] u16 command
[2] u8 button (0=left, 1=right)
[3] u16 id
[5] u16 item
*/
define("SERVER_DAMAGE",0x35);
/*
u16 command
u8 amount
*/
define("SERVER_PASSWORD",0x36);
/*
Sent to change password.
[0] u16 TOSERVER_PASSWORD
[2] u8[28] old password
[30] u8[28] new password
*/
define("SERVER_PLAYERITEM",0x37);
/*
Sent to change selected item.
[0] u16 TOSERVER_PLAYERITEM
[2] u16 item
*/
define("SERVER_RESPAWN",0x38);
/*
u16 TOSERVER_RESPAWN
*/
define("SERVER_INTERACT",0x39);
/*
[0] u16 command
[2] u8 action
[3] u16 item
[5] u32 length of the next item
[9] serialized PointedThing
actions:
0: start digging (from undersurface) or use
1: stop digging (all parameters ignored)
2: digging completed
3: place block or item (to abovesurface)
4: use item
(Obsoletes TOSERVER_GROUND_ACTION and TOSERVER_CLICK_ACTIVEOBJECT.)
*/
define("SERVER_REMOVED_SOUNDS",0x3a);
/*
u16 command
u16 len
s32[len] sound_id
*/
define("SERVER_NODEMETA_FIELDS",0x3b);
/*
u16 command
v3s16 p
u16 len
u8[len] form name (reserved for future use)
u16 number of fields
for each field:
u16 len
u8[len] field name
u32 len
u8[len] field value
*/
define("SERVER_INVENTORY_FIELDS",0x3c);
/*
u16 command
u16 len
u8[len] form name (reserved for future use)
u16 number of fields
for each field:
u16 len
u8[len] field name
u32 len
u8[len] field value
*/
define("SERVER_REQUEST_MEDIA",0x40);
/*
u16 command
u16 number of files requested
for each file {
u16 length of name
string name
}
*/
define("SERVER_RECEIVED_MEDIA",0x41);
/*
u16 command
*/
?>

3
src/testingground.php Normal file
View File

@ -0,0 +1,3 @@
<?php
var_dump(preg_match("/^[A-Za-z0-9]{27}$/", "aaaaaaaaaaaaa6!aaaaaaaaaaaa"));
?>