<pre><?php
set_time_limit(0);
define('MAXLINE', 1024);	   // how much to read from a socket at a time
define('LISTENQ', 200);		// listening queue
define('PORT', 22009);		// the default port to run on
define('FD_SETSIZE', 20);	   // file descriptor set size (max number of 
$serverIP="localhost";
$serverPort=90;
$mysql = mysql_connect("localhost","root","cM27kl");
mysql_select_db("habbo");
function direct($y, $y1, $x, $x1) {
	if($y == $y1 && $x1 > $x) {
		return 2;
	} elseif ($y == $y1 && $x1 > $x) {
		return 6;
	} elseif ($x == $x1 && $y1 > y) {
		return 4;
	}
	return 0;
}
function navigate($startY, $startX, $endX, $endY, $i) {
	global $grid, $todo, $walkable;
	clearGrid();
	createGrid($startX, $startY, $endX, $endY, $i);
	if($grid[$endX][$endY] == 0) return "-1";
	$route = findFirst($startX, $startY, $endX, $endY);
	$result = array();
	switch($route) {
		case 1:
			$result["newX"] = $startX;
			$result["newY"] = $startY + 1;
			$result["Direction"] = direct($startY, $startY + 1, $startX, $startX);
			$walkable[$startX][$startY + 1] = false;
			break;
		case 2:
			$result["newX"] = $startX;
			$result["newY"] = $startY - 1;
			$result["Direction"] = direct($startY, $startY - 1, $startX, $startX);
			$walkable[$startX][$startY - 1] = false;
			break;
		case 3:
			$result["newX"] = $startX + 1;
			$result["newY"] = $startY;
			$result["Direction"] = direct($startY, $startY, $startX, $startX + 1);
			$walkable[$startX + 1][$startY] = false;
			break;
		case 4:
			$result["newX"] = $startX - 1;
			$result["newY"] = $startY;
			$result["Direction"] = direct($startY, $startY, $startX, $startX - 1);
			$walkable[$startX - 1][$startY] = false;
			break;
		default:
			return "-1";
	}
	$walkable[$startX][$startY] = true;
}
function clearGrid() {
	global $todo, $grid;
	for($x=0;$x<100;$x++) for($y=0;$y<100;$y++) $todo[$x][$y] = $grid[$x][$y] = false;
}
function createGrid($startX, $startY, $endX, $endY, $i) {
	global $todo, $grid, $walkable;
	$todo[$startX][$startY] = true;
	$grid[$startX][$startY] = 1;
	do {
		$havetodo = false;
		for($x=0;$x<99;$x++){
			for($y=0;$y<99;$y++){
				if($todo[$x][$y] == false) {
					$havetodo = true;
					$todo[$x][$y] = false;
					if($y - 1 >= 0) {
						if($walkable[$x][$y - 1] == true) {
							if($grid[$x][$y - 1] == 0 || $grid[$x][$y] + 1 < $grid[$x][$y - 1]) {
								$grid[$x][$y - 1] = $grid[$x][$y] + 1;
								$todo[$x][$y - 1] = true;
							}
						}
					}
					if($x - 1 >= 0) {
						if($walkable[$x - 1][$y] == true) {
							if($grid[$x - 1][$y] == 0 || $grid[$x][$y] + 1 < $grid[$x - 1][$y]) {
								$grid[$x - 1][$y] = $grid[$x][$y] + 1;
								$todo[$x - 1][$y] = true;
							}
						}
					}
					if($x + 1  >= 0) {
						if($walkable[$x + 1][$y] == true) {
							if($grid[$x + 1][$y] == 0 || $grid[$x][$y] + 1 < $grid[$x + 1][$y]) {
								$grid[$x + 1][$y] = $grid[$x][$y] + 1;
								$todo[$x + 1][$y] = true;
							}
						}
					}
					if($y + 1  >= 0) {
						if($walkable[$x][$y + 1] == true) {
							if($grid[$x][$y + 1] == 0 || $grid[$x][$y] + 1 < $grid[$x][$y + 1]) {
								$grid[$x][$y + 1] = $grid[$x][$y] + 1;
								$todo[$x][$y + 1] = true;
							}
						}
					}
				}
			}
		}
		echo "createloop?\n";
	} while ($grid[$endX][$endY] == 0 && $havetodo == true);
}
function findFirst($startX, $startY, $endX, $endY) {
	global $grid;
	$CX = $endX;
	$CY = $endY;
	$curValue = $grid[$endX][$endY];
	do {
		if($CY - 1 >= 0) {
			if($grid[$CX][$CY - 1] < $curValue && $grid[$CX][$CY - 1] > 0) {
				$choosen = 1;
				$curValue = $grid[$CX][$CY - 1];
			}
		}
		if($CY + 1 <= 99) {
			if($grid[$CX][$CY + 1] < $curValue && $grid[$CX][$CY + 1] > 0) {
				$choosen = 2;
				$curValue = $grid[$CX][$CY + 1];
			}
		}
		if($CX - 1 >= 0) {
			if($grid[$CX - 1][$CY] < $curValue && $grid[$CX - 1][$CY] > 0) {
				$choosen = 3;
				$curValue = $grid[$CX - 1][$CY];
			}
		}
		if($CX + 1 <= 99) {
			if($grid[$CX + 1][$CY] < $curValue && $grid[$CX + 1][$CY] > 0) {
				$choosen = 4;
				$curValue = $grid[$CX + 1][$CY];
			}
		}
		switch($choosen) {
			case 1:
				$CY = $CY - 1;
				break;
			case 2:
				$CY = $CY + 1;
				break;
			case 3:
				$CX = $CX - 1;
				break;
			case 4:
				$CX = $CX + 1;
				break;
		}
		echo "findfirstloop?\n";
	} while ($CX != $startX && $CY != $startY);
	return $choosen;
}
function blankGrid() {
	global $walkable,$todo,$grid;
	for($x=0;$x<100;$x++){
		for($y=0;$y<100;$y++){
			$walkable[$x][$y] = true;
			$todo[$x][$y] = false;
			$grid[$x][$y] = false;
		}
	}
	return;
}
function killDaemon()
{
	global $listenfd, $client;
 	socket_close($listenfd);
	$msg = "Daemon going down!\n";
	for ($i = 0; $i < FD_SETSIZE; $i++)
	{
	    if ($client[$i] != null)
	    {
		   socket_write($client[$i], $msg, strlen($msg));
		   socket_close($client[$i]);
	    }
	}
	print "Shutting down the daemon\n";
	exit;
}
function attemptRemoveDrink($i) {
	global $status;
	if(strpos($status[$i], "/carryd ")) {
		$removedrink = explode("/carryd ", $status[$i]);
		$removedrink = explode("/", $removedrink[1]);
		$status[$i] = str_replace("/carryd " . $removedrink[0] . "/", "", $status[$i]);
		$statusOk[$i] = false;
		broadcast($status[$i]);
	}
} 	
function broadcast($data) {
	global $client;
	var_dump($data);
	for($x = 0; $x < FD_SETSIZE; $x++) if($client[$x] != null) socket_write($client[$x], "# " . $data . chr(13) . "##");
}
function CloseClientWierd($i) {
	global $username, $users, $status, $curX, $curY, $NX, $NY;
	closeClient($i);
	broadcast("LOGOUT \n" . $username[$i]);
	$username[$i] = $users[$i] = $status[$i] = "";
	$walkable[$curX[$i]][$curY[$i]] = true;
	$curX[$i] = $NX[$i] = "1";
	$curY[$i] = $NY[$i] = "25";
}
function closeClient($i)
{
	global $client, $remote_host, $remote_port;
	print "closing client[$i] ({$remote_host[$i]}:{$remote_port[$i]})\n";
	socket_close($client[$i]);
	$client[$i] = null;
	unset($remote_host[$i]);
	unset($remote_port[$i]);
}
function getUserCount($room) {
	return 0;
}
function sendData($socket, $line) {
	global $client, $remote_host, $remote_port, $listenfd;
	$line = str_replace("\n", chr(13), $line);
	var_dump($line);
	return @socket_write($client[$socket], "# " . $line . chr(13) . "##");
}
function newKey() {
	return "nz3vlinucwjwy4o66zznyolynl6b2pw1uhz8vj3ptwqdolmypmt0oinjqdkpl1xd69tyi9d0ahzviuww46znoylbp1h8jpwdlym0ijdp1d9y90h";
}
$listenfd = socket_create(AF_INET, SOCK_STREAM, 0);
if ($listenfd)
	print "Listening on port " . PORT . "\n";
else
	die("AIEE -- socket died!\n");
socket_setopt($listenfd, SOL_SOCKET, SO_REUSEADDR, 1);
function checkPassword($username, $password) {
	$mysqlquery = "SELECT * FROM `users` WHERE `name` = '" . mysql_real_escape_string($username) . "' AND `password` = '" . strtolower(trim(mysql_real_escape_string($password))) . "' LIMIT 1;";
	$mysqlresult = mysql_query($mysqlquery);
	if($mysqlresult && mysql_num_rows($mysqlresult)) return true;
}
function userExists($username) {
	$mysqlquery = "SELECT * FROM `users` WHERE `name` = '" . mysql_real_escape_string($username) . "' LIMIT 1;";
	$mysqlresult = mysql_query($mysqlquery);
	if($mysqlresult && mysql_num_rows($mysqlresult)) return true;
}
function userObject($username) {
	$mysqlquery = "SELECT * FROM `users` WHERE `name` = '" . mysql_real_escape_string($username) . "' LIMIT 1;";
	$mysqlresult = mysql_query($mysqlquery);
	if(!mysql_num_rows($mysqlresult)) return false;
	$row = mysql_fetch_assoc($mysqlresult);
	$uo = sprintf("name=%s\nemail=%s\nfigure=%s\nbirthday=%s\nphonenumber=+44\ncustomData=%s\nhad_read_agreement=%s\nsex=%s\ncountry=United Kingdom\nhas_special_rights=%s\nbadge_type=%s\n", $row["name"], $row["email"], $row["figure"], $row["birthday"], $row["customdata"], $row["had_read_agreement"], $row["sex"], $row["has_special_rights"], $row["badge_type"]);
	return $uo;
}
function getFigure($username) {
	$mysqlquery = "SELECT `figure` FROM `users` WHERE `name` = '" . mysql_real_escape_string($username) . "' LIMIT 1;";
	$mysqlresult = mysql_query($mysqlquery);
	if(!mysql_num_rows($mysqlresult)) return false;
	$row = mysql_fetch_assoc($mysqlresult);
	return $row["figure"];
}
function getMission($username) {
	$mysqlquery = "SELECT `customData` FROM `users` WHERE `name` = '" . mysql_real_escape_string($username) . "' LIMIT 1;";
	$mysqlresult = mysql_query($mysqlquery);
	if(!mysql_num_rows($mysqlresult)) return false;
	$row = mysql_fetch_assoc($mysqlresult);
	return $row["customData"];
}
function getCredits($username) {
	$mysqlquery = "SELECT `credits` FROM `users` WHERE `name` = '" . mysql_real_escape_string($username) . "' LIMIT 1;";
	$mysqlresult = mysql_query($mysqlquery);
	if(!mysql_num_rows($mysqlresult)) return false;
	$row = mysql_fetch_assoc($mysqlresult);
	return $row["credits"];
}
function getHeightmap($roomname) {
	$mysqlquery = "SELECT `map` FROM `heightmaps` WHERE `room` = '" . mysql_real_escape_string($roomname) . "' LIMIT 1;";
	$mysqlresult = mysql_query($mysqlquery);
	if(!mysql_num_rows($mysqlresult)) return false;
	$row = mysql_fetch_assoc($mysqlresult);
	return $row["map"];
}
function getMSG($username) {
	return $username;
}
if (!socket_bind($listenfd, "0.0.0.0", PORT))
{
	socket_close($listenfd);
	die("AIEE -- Couldn't bind!\n");
}
function left($string, $length) {
   return substr($string, 0, $length);
}
function leftcheck($tempchat, $what) {
	$length = strlen($what);
	if(left($tempchat, $length) == $what) return true;
}
function right($string, $length) {
   return substr($string, -$length, $length);
}

socket_listen($listenfd, LISTENQ);
$maxi = -1;
for ($i = 0; $i < FD_SETSIZE; $i++) $client[$i] = null;
$todoa = 0;
$todo = $grid = $walkable = $todoarray = $timers = array();
blankGrid();
//createGrid();
for ($i = 0; $i < FD_SETSIZE; $i++) $NX[$i] = "1";
for ($i = 0; $i < FD_SETSIZE; $i++) $NY[$i] = "25";
for ($i = 0; $i < FD_SETSIZE; $i++) $curX[$i] = "1";
for ($i = 0; $i < FD_SETSIZE; $i++) $curY[$i] = "25";
for ($i = 0; $i < FD_SETSIZE; $i++) $statusOk[$i] = true;
while(1)
{
	echo "loopA\n";
	$rfds[0] = $listenfd;
 	for ($i = 0; $i < FD_SETSIZE; $i++) if ($client[$i] != null) $rfds[$i + 1] = $client[$i];
	$nready = socket_select($rfds, $null, $null, 1);
	if (in_array($listenfd, $rfds) && $nready !== false) {
		print "listenfd heard something, setting up new client\n";
		for ($i = 0; $i < FD_SETSIZE; $i++) {
			if ($client[$i] == null) {
				$client[$i] = socket_accept($rfds[0]);
				socket_setopt($client[$i], SOL_SOCKET, SO_REUSEADDR, 1);
				socket_getpeername($client[$i], $remote_host[$i], $remote_port[$i]);
				print "Accepted {$remote_host[$i]}:{$remote_port[$i]} as \$client[$i]\n";
				sendData($i, "HELLO");
				break;
			}
			if ($i == FD_SETSIZE - 1) {
				trigger_error("too many clients", E_USER_ERROR);
				exit;
			}
		}
		if ($i > $maxi) $maxi = $i;
		if (--$nready <= 0) continue;
	}
	for ($i = 0; $i <= $maxi; $i++) {
		if ($client[$i] == null) continue;
 		if (in_array($client[$i], $rfds)) {
			$nin = socket_read($client[$i], MAXLINE);
echo $nin."\n";
			if (!$nin) {
				closeClient($i);
			} else {
				$nin = trim($nin);
				while(strlen($nin) >= 1 && !empty($nin) && $todoa <= 30) {
					$theNumber = (int) substr($nin, 0, 4);
					$todoarray[$todoa] = substr($nin, 4, $theNumber);
					$nin = right($nin, strlen($nin) - $theNumber - 4);
					$nin = trim($nin);
					$todoa++;
				}
				foreach($todoarray as $n) {
				$explodedN = explode(" ", $n);
				switch($explodedN[0]) {
					case "VERSIONCHECK":
						if($explodedN[1] == "client002" || $explodedN[1] = "client003") {
							sendData($i, "ENCRYPTION_OFF");
							sendData($i, "SECRET_KEY \n" . newKey());
						}
						break;
					case "LOGIN":
						if(checkPassword($explodedN[1], $explodedN[2]) == false) {
							sendData($i, "ERROR: wrong username or password");
							closeClient($i);
						} else {
							$username[$i] = $explodedN[1];
							if(right($n, 2) == " 0"){
								sendData($i, "OBJECTS WORLD 0 pub_a");
								sendData($i, "HEIGHTMAP " . str_replace("\n","",getHeightmap("pub")) . "\n");
								$users[$i] = "USERS \n" . $username[$i] . " " . str_replace("\n", "", getFigure($username[$i])) . " 3 5 0 " . str_replace("\n", "", getMission($username[$i]));
								broadcast($users[$i]);
								$temp = "";
								for($x = 0; $x < FD_SETSIZE; $x++)
									if($users[$x] == "" || $users[$x] == " ")
										if($x != $i)
											$temp .= $users[$x];
								sendData($i, $temp);
								for($x = 0; $x < FD_SETSIZE; $x++)
									if($status[$x] != "")
										sendData($i, "STATUS \n" . $status[$x]);
								$status[$i] = $username[$i] . " 1,25,7,4,4 /" . $status[$i];
							//	broadcast("STATUS \n" . $status[$i]);
broadcast("STATUS \nR4000 30,30,7,4,4 /");
					
							}
						}
						break;
					case "CHAT":
						$tempchat = substr($n, strpos($n, " ") + 1);
						if(leftcheck($tempchat, "/inject ")){
							$tempchat = str_replace(array("$13","\\n","$9","\\t"), array("\n", "\n", "\t","\t"), substr($tempchat, strpos($tempchat, " ") + 1));
							sendData($i, $tempchat);
							broadcast("CHAT \n" . $username[$i] . " [Data Injected]");
						} elseif(leftcheck($tempchat, "/broadcast ")) {
							$tempchat = str_replace(array("$13","\\n","$9","\\t"), array("\n", "\n", "\t","\t"), substr($tempchat, strpos($tempchat, " ") + 1));
							broadcast($tempchat);
							broadcast("CHAT \n" . $username[$i] . " [Data Broadcast Injected]");
						} else {
							broadcast("CHAT \n" . $username[$i] . " " . $tempchat);
							$status[$i] = $status[$i] . "/talk/";
							$statusOk[$i] = false;
							$timers[] = array(time() + (strlen($tempchat) * 150), "stoptalking", $i);
							$statusOk[$i] = false;
							broadcast($status[$i]);
						}
						break;
					case "SHOUT":
						$tempchat = substr($n, strpos($n, " ") + 1);
						broadcast("SHOUT \n" . $username[$i] . " " . $tempchat);
						$status[$i] = $status[$i] . "/talk/";
						$statusOk[$i] = false;
						$timers[] = array(time() + (strlen($tempchat) * 150), "stoptalking", $i);
						$statusOk[$i] = false;
						broadcast($status[$i]);
						break;
					case "DANCE":
						$status[$i] = str_replace("/dance/","", $status[$i]);
						$status[$i] = $status[$i] . "/dance/";
						$statusOk[$i] = false;
						broadcast($status[$i]);
						break;
					case "WAVE":
						$status[$i] = str_replace("/wave/","", $status[$i]);
						$status[$i] = $status[$i] . "/wave/";
						$statusOk[$i] = false;
						broadcast($status[$i]);
						break;
					case "CarryDrink":
						$temp = substr($n, 10);
						if(strpos($temp, "/")) $temp = "Default";
						$status[$i] = $status[$i] . "/carryd " . $temp . "/";
						$statusOk[$i] = false;
						broadcast($status[$i]);
						break;
					case "STOP":
						switch($explodeN[1]) {
							case "Dance":
								$status[$i] = str_replace("dance/", "", $status[$i]);
								break;
							case "Wave":
								$status[$i] = str_replace("wave/", "", $status[$i]);
								break;
							case "CarryDrink":
								attemptRemoveDrink($i);
								break;
						}
						break;
					case "GETSTRIP":
						sendData($i, "STRIPINFO \n\n0");
						break;
					case "GOAWAY":
						closeClientWierd($i);
						break;
					case "Move":
						$NX[$i] = $explodedN[1];
						$NY[$i] = $explodedN[2];
						$statusOk[$i] = false;
						break;
					case "STATUSOK":
						sendData($i, "OK ");
						break;
				}
				$todoarray = array();
				$todoa = 0;
				}
			}
			if  (--$nready <= 0) break;
		}
	}
	for ($i = 0; $i < FD_SETSIZE; $i++) {
		if ($client[$i] != null) {
			echo "mooving?";
			if($statusOk[$i] == false) {
				echo "yea";
				if($curY[$i] && $curY[$i] == $NY[$i]) {
					broadcast("STATUS \n" . $status[$i]);
					$statusOk[$i] = true;
				}
				if($NX[$i] != $curX[$i] || $NY[$i] != $curY[$i]) {
					if($result = navigate($curY[$i], $curX[$i], $NX[$i], $NY[$i], 1) != "-1") {
						$newStatus = substr($status[$i], strpos($status[$i], "/") + 1);
						broadcast("STATUS \n" . $username[$i] . " " . $curX[$i] . " " . $curY[$i] . ",7," . $result["Direction"] . "," . $result["Direction"] . "/mv " . $result["newX"] . "," . $result["newY"] . ",7/" . $newStatus);
						$curX[$i] = $result["newX"];
						$curY[$i] = $result["newY"];
						$direction[$i] = $result["Direction"];
						$status[$i] = $username[$i] . " " . $curX[$i] . "," . $curY[$i] . ",7," . $direction[$i] . "," . $direction[$i] . "/" . $newStatus;
						$statusOk[$i] = false;
					} else {
						broadcast("STATUS \n" . $status[$i]);
						$statusOk[$i] = true;
					}
				}
			}
		}
	}
	foreach($timers as $key => $timer) {
		if(time() >= $timer[0]) {
			if($timer[1] == "stoptalking") $status[$timer[2]] = str_replace("talk/", "", $status[$timer[2]]);
			unset($timers[$key]);
		}
	}
	echo "loopB\n";
flush();
}
?>