Makes the autoload work without using a register function, as well as changes the networking to OpenSwoole so binary data can be send to the client

main
Tiger 2024-02-23 22:26:39 +01:00
parent 6b0d439f7c
commit fcee1f89d4
5 changed files with 155 additions and 1536 deletions

View File

@ -1,11 +1,11 @@
{
"require": {
"react/event-loop": "^1.5",
"react/http": "^1.9",
"react/stream": "^1.3",
"react/async": "^4.2",
"react/promise": "^3.1",
"react/socket": "^1.15",
"cboden/ratchet": "^0.4.4"
"openswoole/core": "22.1.5",
"openswoole/ide-helper": "~22.0.1"
},
"autoload": {
"psr-4": {
"Emulator\\": "src/Emulator"
}
}
}

1586
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -2,10 +2,6 @@
require_once 'vendor/autoload.php';
spl_autoload_register(function(string $class) {
require_once str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
});
use Emulator\HabboEnvironment;
HabboEnvironment::getInstance()->initialize();

View File

@ -7,33 +7,22 @@ use Emulator\Encoding\ByteEncoding;
use Emulator\Messages\Incoming\ClientMessage;
use Emulator\Messages\MessageHandler;
use Emulator\Network\Game\Sessions\Session;
use Override;
use Ratchet\ConnectionInterface;
use Ratchet\Http\HttpServer;
use Ratchet\RFC6455\Messaging\MessageInterface;
use Ratchet\Server\IoServer;
use Ratchet\WebSocket\MessageComponentInterface;
use Ratchet\WebSocket\WsConnection;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\Loop;
use React\Socket\SocketServer;
use OpenSwoole\WebSocket\Server;
use OpenSwoole\Http\Request;
use OpenSwoole\WebSocket\Frame;
class GameNetworkServer implements MessageComponentInterface {
class GameNetworkServer {
private static ?GameNetworkServer $instance = null;
private array $sessions;
public function start(int $port): void {
$loop = Loop::get();
$this->sessions = [];
$socketServer = new SocketServer("127.0.0.1:{$port}", loop: $loop);
new IoServer(
new HttpServer(
new WsServer($this)
),
$socketServer,
$loop
);
$server = new Server("127.0.0.1", $port);
$server->on('Start', [$this, 'onStart']);
$server->on('Open', [$this, 'onOpen']);
$server->on('Close', [$this, 'onClose']);
$server->on('Disconnect', [$this, 'onDisconnect']);
$server->on('Message', [$this, 'onMessage']);
$server->start();
}
public static function getInstance(): GameNetworkServer {
@ -44,27 +33,32 @@ class GameNetworkServer implements MessageComponentInterface {
return self::$instance;
}
#[Override] function onOpen(ConnectionInterface $conn): void {
$this->sessions[$conn->resourceId] = new Session(new WsConnection($conn));
function onStart(Server $server): void {
Logger::info("Websocket server is started at $server->host:$server->port");
}
#[Override] function onClose(ConnectionInterface $conn): void {
unset($this->sessions[$conn->resourceId]);
function onOpen(Server $server, Request $request): void {
$this->sessions[$request->fd] = new Session($server, $request);
}
#[Override] function onError(ConnectionInterface $conn, \Exception $e): void {
Logger::fatal($e->getMessage());
function onClose(Server $server, int $fd): void {
Logger::info("Connection #$fd has been closed");
unset($this->sessions[$fd]);
}
#[Override] public function onMessage(ConnectionInterface $conn, MessageInterface $msg): void {
$raw = $msg->getPayload();
$data = unpack('C*', $raw);
function onDisconnect(Server $server, int $fd): void {
Logger::info("Connection #$fd has disconnected");
unset($this->sessions[$fd]);
}
function onMessage(Server $server, Frame $frame): void {
$data = unpack('C*', $frame->data);
if (count($data) >= 6) {
$length = ByteEncoding::getInt32(array_slice($data, 1, 4));
$packet = array_slice($data, 4, $length);
MessageHandler::getInstance()->handlePacket($this->sessions[$conn->resourceId], new ClientMessage($packet));
MessageHandler::getInstance()->handlePacket($this->sessions[$frame->fd], new ClientMessage($packet));
}
}
}

View File

@ -5,15 +5,16 @@ namespace Emulator\Network\Game\Sessions;
use Emulator\Encoding\ByteEncoding;
use Emulator\Messages\Outgoing\IMessageComposer;
use Emulator\Messages\Outgoing\ServerMessage;
use Ratchet\RFC6455\Messaging\Frame;
use Ratchet\RFC6455\Messaging\Message;
use Ratchet\WebSocket\WsConnection;
use OpenSwoole\Http\Request;
use OpenSwoole\WebSocket\Server;
readonly class Session {
private WsConnection $connection;
private Server $server;
private Request $request;
public function __construct(WsConnection $connection) {
$this->connection = $connection;
public function __construct(Server $server, Request $request) {
$this->server = $server;
$this->request = $request;
}
public function sendComposer(IMessageComposer $composer): void {
@ -21,20 +22,6 @@ readonly class Session {
$composer->compose($message);
$data = array_merge(ByteEncoding::int32ToArray(count($message->getPacket())), $message->getPacket());
$this->connection->send(new Frame(pack('C*', ...$data), true, Frame::OP_BINARY));
$this->server->push($this->request->fd, pack('C*', ...$data), Server::WEBSOCKET_OPCODE_BINARY);
}
function encode($text) {
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if ($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
}