/**
   * Handles an incoming plugin message.
   *
   * @param data The data of the incoming message
   * @param proxiedPlayer The player who received the message
   */
  @Override
  public void handleIncomingMessage(byte[] data, ProxiedPlayer proxiedPlayer) {
    try {
      DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(data));

      int id = inputStream.readInt();
      if (!MessagingLib.getMessageRegistry().isPluginMessageRegistered(id)) {
        return;
      }

      PluginMessage pluginMessage =
          MessagingLib.getMessageRegistry()
              .getPluginMessage(id)
              .getClass()
              .getConstructor()
              .newInstance();

      pluginMessage.read(inputStream);

      if (this.pluginMessageListeners.containsKey(id)) {
        for (MethodContainer methodContainer : this.pluginMessageListeners.get(id)) {
          try {
            methodContainer
                .getMethod()
                .invoke(methodContainer.getMessageListener(), pluginMessage, proxiedPlayer);
          } catch (Exception e) {
            throw new PluginMessageEventException(
                "Error while performing a plugin message event", e);
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * Sends a plugin message to the specified player.
   *
   * @param pluginMessage The message to send
   * @param proxiedPlayer The player to send the message to
   */
  @Override
  public void sendPluginMessage(PluginMessage pluginMessage, ProxiedPlayer proxiedPlayer) {
    try {
      if (proxiedPlayer != null) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DataOutputStream outputStream = new DataOutputStream(byteArrayOutputStream);
        if (BungeeCordMessage.class.isAssignableFrom(pluginMessage.getClass())) {

          BungeeCordMessage bungeeCordMessage = (BungeeCordMessage) pluginMessage;
          outputStream.writeUTF(bungeeCordMessage.getSubChannel());
          bungeeCordMessage.write(outputStream);
          proxiedPlayer.sendData(
              MessagingLib.BUNGEE_CORD_CHANNEL, byteArrayOutputStream.toByteArray());
        } else {
          outputStream.writeInt(pluginMessage.getClass().getName().hashCode());
          pluginMessage.write(outputStream);
          proxiedPlayer.sendData(
              MessagingLib.MESSAGING_LIB_CHANNEL, byteArrayOutputStream.toByteArray());
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }