Adds a Dictionary type for safer array creation in a similar fashion as C#
parent
792c3939ab
commit
6dd2118267
|
@ -7,27 +7,29 @@ use Emulator\Messages\Incoming\ClientMessage;
|
|||
use Emulator\Messages\Incoming\Handshake\ReleaseVersionMessageEvent;
|
||||
use Emulator\Messages\Incoming\Handshake\SecurityTicketMessageEvent;
|
||||
use Emulator\Messages\Incoming\Header;
|
||||
use Emulator\Messages\Incoming\IMessageEvent;
|
||||
use Emulator\Network\Game\Sessions\Session;
|
||||
use Emulator\Utilities\Dictionary;
|
||||
use SplObjectStorage;
|
||||
|
||||
class MessageHandler {
|
||||
private SplObjectStorage $handlers;
|
||||
private Dictionary $handlers;
|
||||
|
||||
public function __construct() {
|
||||
$this->handlers = new SplObjectStorage();
|
||||
$this->handlers = new Dictionary(IMessageEvent::class);
|
||||
}
|
||||
|
||||
public function initialize(): void {
|
||||
$this->handlers[Header::ReleaseVersion] = new ReleaseVersionMessageEvent();
|
||||
$this->handlers[Header::SecurityTicket] = new SecurityTicketMessageEvent();
|
||||
$this->handlers->add(Header::ReleaseVersion, new ReleaseVersionMessageEvent());
|
||||
$this->handlers->add(Header::SecurityTicket, new SecurityTicketMessageEvent());
|
||||
|
||||
Logger::info("Loaded " . count($this->handlers) . " message handlers");
|
||||
Logger::info("Loaded {$this->handlers->count()} message handlers");
|
||||
}
|
||||
|
||||
public function handlePacket(Session $session, ClientMessage $request): void {
|
||||
if (($header = Header::tryFrom($request->getHeader()))) {
|
||||
if ($this->handlers->contains($header)) {
|
||||
$this->handlers[$header]->handle($session, $request);
|
||||
if ($this->handlers->containsKey($header->value)) {
|
||||
$this->handlers->get($header)->handle($session, $request);
|
||||
} else {
|
||||
Logger::warn("[{$request->getHeader()}] [$header->name] - Unregistered!");
|
||||
}
|
||||
|
|
|
@ -7,9 +7,7 @@ use Emulator\Messages\Outgoing\IMessageComposer;
|
|||
use Emulator\Messages\Outgoing\ServerMessage;
|
||||
use Override;
|
||||
|
||||
class AuthenticatedComposer implements IMessageComposer
|
||||
{
|
||||
|
||||
class AuthenticatedComposer implements IMessageComposer {
|
||||
#[Override] function compose(ServerMessage $message): void {
|
||||
}
|
||||
|
||||
|
|
|
@ -7,14 +7,15 @@ use Emulator\Encoding\ByteEncoding;
|
|||
use Emulator\Messages\Incoming\ClientMessage;
|
||||
use Emulator\Messages\MessageHandler;
|
||||
use Emulator\Network\Game\Sessions\Session;
|
||||
use Emulator\Utilities\Dictionary;
|
||||
use OpenSwoole\WebSocket\Server;
|
||||
use OpenSwoole\Http\Request;
|
||||
use OpenSwoole\WebSocket\Frame;
|
||||
|
||||
class GameNetworkServer {
|
||||
private array $sessions;
|
||||
private Dictionary $sessions;
|
||||
public function __construct(private readonly MessageHandler $messageHandler) {
|
||||
$this->sessions = [];
|
||||
$this->sessions = new Dictionary(Session::class);
|
||||
}
|
||||
|
||||
public function start(int $port): void {
|
||||
|
@ -32,17 +33,17 @@ class GameNetworkServer {
|
|||
}
|
||||
|
||||
function onOpen(Server $server, Request $request): void {
|
||||
$this->sessions[$request->fd] = new Session($server, $request);
|
||||
$this->sessions->add($request->fd, new Session($server, $request));
|
||||
}
|
||||
|
||||
function onClose(Server $server, int $fd): void {
|
||||
Logger::info("Connection #$fd has been closed");
|
||||
unset($this->sessions[$fd]);
|
||||
$this->sessions->remove($fd);
|
||||
}
|
||||
|
||||
function onDisconnect(Server $server, int $fd): void {
|
||||
Logger::info("Connection #$fd has disconnected");
|
||||
unset($this->sessions[$fd]);
|
||||
$this->sessions->remove($fd);
|
||||
}
|
||||
|
||||
function onMessage(Server $server, Frame $frame): void {
|
||||
|
@ -52,7 +53,7 @@ class GameNetworkServer {
|
|||
$length = ByteEncoding::getInt32(array_slice($data, 1, 4));
|
||||
$packet = array_slice($data, 4, $length);
|
||||
|
||||
$this->messageHandler->handlePacket($this->sessions[$frame->fd], new ClientMessage($packet));
|
||||
$this->messageHandler->handlePacket($this->sessions->get($frame->fd), new ClientMessage($packet));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Emulator\Utilities;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Dictionary {
|
||||
private array $arr;
|
||||
public function __construct(private readonly string $valueType) {
|
||||
$this->arr = [];
|
||||
}
|
||||
|
||||
public function add(mixed $key, mixed $value): void {
|
||||
if (!is_int($key) && !is_string($key) && !TypeChecker::isEnum($key)) {
|
||||
throw new InvalidArgumentException('Key must be an integer, string or an enum');
|
||||
}
|
||||
|
||||
if (!$value instanceof $this->valueType) {
|
||||
throw new InvalidArgumentException("Value must be an instance of {$this->valueType}");
|
||||
}
|
||||
|
||||
if (TypeChecker::isEnum($key)) {
|
||||
$key = $key->value;
|
||||
}
|
||||
|
||||
if (array_key_exists($key, $this->arr)) {
|
||||
throw new InvalidArgumentException("Key $key already exists");
|
||||
}
|
||||
|
||||
$this->arr[$key] = $value;
|
||||
}
|
||||
|
||||
public function get($key): mixed {
|
||||
if (TypeChecker::isEnum($key)) {
|
||||
$key = $key->value;
|
||||
}
|
||||
|
||||
return $this->arr[$key] ?? null;
|
||||
}
|
||||
|
||||
public function containsKey($key): bool {
|
||||
if (TypeChecker::isEnum($key)) {
|
||||
$key = $key->value;
|
||||
}
|
||||
|
||||
return array_key_exists($key, $this->arr);
|
||||
}
|
||||
|
||||
public function count(): int {
|
||||
return count($this->arr);
|
||||
}
|
||||
|
||||
public function remove($key): void {
|
||||
if (TypeChecker::isEnum($key)) {
|
||||
$key = $key->value;
|
||||
}
|
||||
|
||||
unset($this->arr[$key]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace Emulator\Utilities;
|
||||
|
||||
class TypeChecker {
|
||||
public static function isEnum($var): bool {
|
||||
return is_object($var) && enum_exists(get_class($var));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue