<?php

class mcpi{
	
	private const packet = "\x02\x00\x00\x00\x00\x00\x01\xbe\xdb\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x12\x34\x56\x78";
	
	public function ping(string $ip, int $port = 19132, int $timeout = 3){
		
		if(!($sock = socket_create(AF_INET, SOCK_DGRAM, 0))){
			
			throw new Exception("Failed to connect");
		}
		
		if(!socket_sendto($sock, mcpi::packet, strlen(mcpi::packet), 0, $ip, $port)){
			
			throw new Exception("Failed to send data");
		}
		
		socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, ["sec" => $timeout, "usec" => 0]);
		
		// get string size
		// for some reason, not using msg_peek makes the second
		// socket_recv call hang
		if(socket_recv($sock, $strlen, 36, MSG_PEEK | MSG_WAITALL) === false){
			
			throw new Exception("Failed to receive datalen");
		}
		
		$strlen = unpack("c", substr($strlen, 34, 35))[1];
		
		if(socket_recv($sock, $reply, (35 + $strlen), MSG_WAITALL) === false){
			
			throw new Exception("Failed to receive string");
		}

		$reply = substr($reply, 35, (35 + $strlen));
		
		$reply = explode(";", $reply);
		
		if(count($reply) !== 3){
			
			throw new Exception("Received malformed string");
		}
		
		$reply = [
			"game" => $reply[0],
			"type" => $reply[1],
			"name" => $reply[2]
		];
		
		return $reply;
	}
}