<?php class GameServer extends SocketServer { function on_connect($clientID) { $cObj = $this->getClientObject($clientID); // Attempt to read from the socket to catch the handshake from a WebSocket connection (without waiting if nothing's there) // @socket_recv($cObj->getSocket(), $input, 2048, MSG_DONTWAIT); if (substr_count($input, "Upgrade: WebSocket") > 0) { list($resource,$host,$origin) = $this->getHeaders($input); if ($resource == "") { $resource = WS_RESOURCE; $host = WS_HOST; $origin = WS_ORIGIN; } $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . "Upgrade: WebSocket\r\n" . "Connection: Upgrade\r\n" . "WebSocket-Origin: $origin\r\n" . "WebSocket-Location: ws://" . $host . $resource . "\r\n" . "\r\n"; $cObj->setClientType(GC_WEBSOCKET); $cObj->handshake = true; socket_write($cObj->getSocket(), $upgrade.chr(0),strlen($upgrade.chr(0))); echo "Good handshake for client [$clientID]\n"; } else { $cObj->setClientType(GC_TELNET); $cObj->handshake = true; $cObj->send("Welcome to Phud!\nType a name for your character and press enter to continue.\r\n"); echo "Client [$clientID] set to GC_TELNET\n"; } } function post_connect($clientID) { } function on_disconnect($clientID) { $cObj = $this->getClientObject($clientID); global $game; if (is_object($game) && is_object($cObj) && $cObj->getCharEID() > 0) { // Remove the connection from the game object // $char = getCharMem($cObj->getCharEID()); echo "Disconnecting: {$char->getName()}\n"; $game->removeConnection($cObj->getCharEID()); } } function on_read($client = -1, $data = "") { $cObj = $this->getClientObject($client); // If this client has NOT sent a handshake request and the server type is GC_WEBSOCKET, // // it's a telnet or other attempt, so set the client's type to GC_TELNET as a fallback // // to prevent sending the handshake unnecessarily. // if ($this->getClientType() == GC_WEBSOCKET && !$cObj->hasHandshake() && substr_count($data, "Upgrade: WebSocket") == 0) { $cObj->setClientType(GC_TELNET); $cObj->handshake = true; } // Only parse the input if the client has completed the handshake (for WebSocket clients) or is a Telnet client // if ($cObj->getClientType() == GC_TELNET || ($cObj->getClientType() == GC_WEBSOCKET && $cObj->hasHandshake())) { // Trim the nasty from WebSocket data (a 0xFF byte appended to every message) // if ($cObj->getClientType() == GC_WEBSOCKET) $data = substr($data, 0, strlen($data) - 1); $break = split("\n", $data); foreach ($break as $i => $temp) { $this->parseClientInput($cObj, $temp); } } } // Overall Game Parser // function parseClientInput(GameClient $cObject, $cdata) { global $game; $cdata = stripEnds($cdata); $fSplit = splitOnce($cdata, " "); //echo "Client [{$cObject->getID()}] sends: $cdata\n"; if (!$fSplit) // One word input... // { $command = $cdata; $data = ""; } else { $command = $fSplit[0]; $data = $fSplit[1]; } // Process user sent commands // if (!$cObject->getCharEID() > 0) { $eid = count($game->getCharacters())+1; // Account for number of rooms, just in case // $name = htmlentities($command); $c = new Character($eid, $name,"A loyal citizen of Phud."); if (is_object($c)) { // Set the character's connection info // global $game; if (is_object($game)) { $cObject->setCharEID($c->getEID()); $cObject->setLastTime(); $game->addConnection($c->getEID(), $cObject); } // Send an extra message for WebSocket's sake... No clue why, except that it works // if ($this->getClientType() == GC_WEBSOCKET) $c->send(""); $c->send("Welcome back to Phud, {$c->getName()}!", "notify"); // Cause the action "look" so the player will see his starting room // look($c->getEID()); map_Refresh($c); // Let everyone in the room know to update the room contents area // $c->getRoom()->send("{$c->getName()} pops into existence....", "sysmessage", $c->getEID()); foreach ($c->getRoom()->getCharacters() as $key => $char) { rc_Update($char); } echo "Logging {$c->getName()} in!\n"; } return true; } else { // Don't let the user spam us // if (microtime(true) - $cObject->getLastTime() <= .35) {return true;} $cObject->setLastTime(); $c = getCharMem($cObject->getCharEID()); if (!is_object($c)) return true; // Signing out // if ($command == "quit") { $c->send("We hope to see you again soon!", "sysmessage"); if ($c->getConnection()->getClientType() == GC_WEBSOCKET) $c->sendDirect("window.top.client.close();"); $c->setOffline(); return true; } if (trim($command) == "") { $c->send("Do nothing on your own time...", "notify"); return true; } else { $command = strtolower($command); if ($command == "say") { say($c->getEID(), $data); return true; } if ($command == "look" || $command == "ql" || $command == "l") { look($c->getEID()); return true; } if ($command == "nw" || $command == "n" || $command == "ne" || $command == "w" || $command == "e" || $command == "sw" || $command == "s" || $command == "se") { // Wanna send the command, as there is no data // move($c->getEID(), $command); return true; } } } } } ?>