diff --git a/src/Emulator/Messages/MessageHandler.php b/src/Emulator/Messages/MessageHandler.php index 9a1ded2..5f74421 100644 --- a/src/Emulator/Messages/MessageHandler.php +++ b/src/Emulator/Messages/MessageHandler.php @@ -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!"); } diff --git a/src/Emulator/Messages/Outgoing/Handshake/AuthenticatedComposer.php b/src/Emulator/Messages/Outgoing/Handshake/AuthenticatedComposer.php index 66142e5..9c84b50 100644 --- a/src/Emulator/Messages/Outgoing/Handshake/AuthenticatedComposer.php +++ b/src/Emulator/Messages/Outgoing/Handshake/AuthenticatedComposer.php @@ -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 { } diff --git a/src/Emulator/Network/Game/GameNetworkServer.php b/src/Emulator/Network/Game/GameNetworkServer.php index d18beb6..1825f32 100644 --- a/src/Emulator/Network/Game/GameNetworkServer.php +++ b/src/Emulator/Network/Game/GameNetworkServer.php @@ -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)); } } } \ No newline at end of file diff --git a/src/Emulator/Utilities/Dictionary.php b/src/Emulator/Utilities/Dictionary.php new file mode 100644 index 0000000..bc2c09b --- /dev/null +++ b/src/Emulator/Utilities/Dictionary.php @@ -0,0 +1,60 @@ +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]); + } +} \ No newline at end of file diff --git a/src/Emulator/Utilities/TypeChecker.php b/src/Emulator/Utilities/TypeChecker.php new file mode 100644 index 0000000..3d84c38 --- /dev/null +++ b/src/Emulator/Utilities/TypeChecker.php @@ -0,0 +1,9 @@ +