Question

Source for packet format: http://wiki.vg/Protocol

I am trying to write a program in php which will send packets to a minecraft server I host. This will likely be for a multiplayer implementation for phones, which do not support the same API formats. The code i have below is my failed attempt to make this work. How can i do this properly? The server is recognizing something, but its either not sending anything back, or something. This below is supposed to send 0x00, the handshake packet to request the stats on the server using the next state ID: 1. Minecraft should be responding with the same ID, but with the server motd, and the player count. For 1.7.2, which this will be for, it'll also send a server-icon.png. But i can safely ignore that data, as it'll be direct connections only.

What am I doing wrong, and how can I fix it?

Main.php

require("socket.php");

$f = getStat("zontreck.dyndns.biz",25565);
/*$za = 0x00;
$za[0] = 74;
$za[1] = "zontreck.dyndns.biz";
$za[2] = 25565;
$za[3] = 1;
*/
$za = array(0x00,"Protocol Version"=>73,
    "Server Address"=>"zontreck.dyndns.biz",
    "Server Port"=>25565,
    "Next State"=>1);
$dd = doWrite(pack("a",$za),$f);
echo("Response from doWrite: " .$dd."\n");
echo("Sending: " . pack("a",$za)."\n");
/*if(doWrite(pack("a",$za),$f))
{
    echo(fgets($f));
} else {
    echo(fgets($f));
}*/

$ff = fgets($f);
//$u = unpack("a",$ff);
fclose($f);
echo("Data from server: " . $ff."\n");
echo("Data from server length: " . strlen($ff)."\n");
//fclose($f);
?>

socket.php

<?

function getStat($url = "",$port=25565)
{
    $f = fsockopen($url,$port);
    return $f;
}

function doWrite($packet,$socket)
{
    return fwrite($socket,$packet);
}


?>

Output from main.php

root@zontreck:/var/www/slmc# php main.php
PHP Notice:  Array to string conversion in /var/www/slmc/main.php on line 16
Response from doWrite: 1
PHP Notice:  Array to string conversion in /var/www/slmc/main.php on line 18
Sending: A
Data from server: 
Data from server length: 0
root@zontreck:/var/www/slmc# 
Was it helpful?

Solution

You'll probably want to take a look at this: https://forums.bukkit.org/threads/web-php-simple-to-use-minecraft-server-status-query.144329/

It's basically some explanation on this library which does exactly what you want: https://github.com/FunnyItsElmo/PHP-Minecraft-Server-Status-Query

It also uses sockets so you could always take some of the code and modify it to your needs, but I strongly advice you just to use the library as-is because it does what you're trying to accomplish.

OTHER TIPS

Both of the commenters are right, you need to revisit how you are doing this.

More specifically, the Minecraft protocol uses UDP, which means you need to have access to the raw socket using socket_create - http://php.net/manual/en/function.socket-create.php

Then you need to build a string that contains all of the of the required packets correctly, as @Marc B outlined. Then you can write that string to the socket. Note that since UDP is both stateless and has no error correction, you will also have to write retry routines if you get an error back.

What you are currently doing is building data structures in one language (PHP), then trying to write them to a wire protocol (totally different), which is pretty much impossible.

It's certainly possible to do this in PHP, but you have to work at a much lower level than you are now doing, with raw sockets, hex data strings and network error handling. I would suggest you look at other PHP libraries which handle UDP data to see if there is some code you can reuse.

There is some code in the socket_create page comments that you might be able to use/learn from. In particular, there is a TFTP example which you might be able to modify.

Not a simple answer, but this is non-trivial to do in any language and PHP isn't really designed for this, so there aren't a lot of examples.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top