Не приостанавливается выполнение события на клиентской стороне

  • Автор темы Автор темы uaa007
  • Дата начала Дата начала

uaa007

Junior Developer
Пытаюсь написать следующий алгоритм: игрок вводит команду "/viewer true" и после этого при нажатии и удерживании на клавишу N рендерится текст "Отпусти кнопку N". Если клавишу N отпускаем - текст "Отпусти кнопку N" исчезает. После чего, вводится команда "/viewer false" и теперь при нажатии на клавишу N текст "Отпусти кнопку N" больше не рендерится.

Проблема: при вводе команды "/viewer false" если используем mp.events.remove(), то текст продолжает отображаться при нажатии на клавишу N, если используем mp.events.reset(), то все события удаляются и, соответственно, команды "/viewer false" и "/viewer true" больше не обрабатываются на клиенте.

Код на сервере:
JavaScript:
mp.events.add({
  playerCommand: (player, command) => {
    const parameters = command.split(/[ ]+/);
    const commandName = parameters[0];
    if (commandName === "viewer") {
      if (parameters[1] === "true") {
        player.call("viewer_client", [true]);
        player.outputChatBox(`При нажатии [N] будет выводиться надпись`);
      } else if (parameters[1] === "false") {
        player.call("viewer_client", [false]);
        player.outputChatBox(`При нажатии [N] надпись выводиться не будет`);
      }
    }
  },
});

Код на клиенте:
Код:
mp.events.add({
  "viewer_client": (bool) => {
    if (bool) {
      mp.events.call("renderOn", renderOn);
      mp.gui.chat.push("Включили");
    } else if (!bool) {
      mp.events.remove("renderOn", renderOn); // Если используем это, то ничего не отключается
      mp.events.reset(); // Если используем это, то событие "gunViewer_client" больше не срабатывает
      mp.gui.chat.push("Выключили");
    }
  },
});

mp.events.add("renderOn", renderOn);
function renderOn() {
  mp.events.add("render", () => {
    if (mp.keys.isDown(78) === true) {
      mp.game.graphics.drawText(`Нажата кнопка N`, [0.5, 0.005], {
        font: 7,
        color: [255, 255, 255, 185],
        scale: [0.5, 0.5],
        outline: false,
      });
    }
  });
}

Примечание: пробовал через класс создавать событие и использовать eventName.destroy() или eventName.enable() - ничего не изменяется. Просто код этот удалил, если нужно - напишу еще раз, дайте знать)
 
Решение
Можно, при желании, событие render вывести в отдельную функцию, чтобы направить работу remove в более точное русло))

Спасибо Lev Angel!
С переменными сущностей, по идее можно еще упростить. Есть встроенный ивент который триггерится на клиенте если их меняешь: https://wiki.rage.mp/index.php?title=Events::addDataHandler

Изменил код на клиенте:

JavaScript:
mp.events.addDataHandler("viewer", function (entity, value) {
  if (entity.type === "player" && value === true) {
    mp.events.add("render", renderOnViewer);
    mp.events.call("render", renderOnViewer);
  } else {
    mp.events.remove("render", renderOnViewer);
  }
});

function renderOnViewer() {
  if (mp.keys.isDown(78) === true) {...
Проблема в том, что ты добавляешь обработчик на render внутри другого своего обработчика renderOn. И когда ты убираешь renderOn, то вложенный обработчик уже был проинициализирован и никуда не денется.
Я бы добавил какую-то переменную или свойство игрока в котором менял значение на true|false в зависимости от команды. И был бы просто render обработчик который смотрел не только на статус нажатия кнопки, но и на значение этой переменной. Таким образом тебе не нужно сам обработчик убирать вообще.
JavaScript:
  mp.events.add("render", () => {
    if (mp.keys.isDown(78) === true && viewerAllowed) {
      mp.game.graphics.drawText(...);
    }
  });
Ну либо выкинуть промежуточный renderOn ивент и вешать/убирать обработчик сразу на render
 
Проблема в том, что ты добавляешь обработчик на render внутри другого своего обработчика renderOn. И когда ты убираешь renderOn, то вложенный обработчик уже был проинициализирован и никуда не денется.
Я бы добавил какую-то переменную или свойство игрока в котором менял значение на true|false в зависимости от команды. И был бы просто render обработчик который смотрел не только на статус нажатия кнопки, но и на значение этой переменной. Таким образом тебе не нужно сам обработчик убирать вообще.
JavaScript:
  mp.events.add("render", () => {
    if (mp.keys.isDown(78) === true && viewerAllowed) {
      mp.game.graphics.drawText(...);
    }
  });
Ну либо выкинуть промежуточный renderOn ивент и вешать/убирать обработчик сразу на render
Отлично, сегодня вечером буду пробовать и скину результат, спасибо большое🥹
 
Проблема в том, что ты добавляешь обработчик на render внутри другого своего обработчика renderOn. И когда ты убираешь renderOn, то вложенный обработчик уже был проинициализирован и никуда не денется.
Я бы добавил какую-то переменную или свойство игрока в котором менял значение на true|false в зависимости от команды. И был бы просто render обработчик который смотрел не только на статус нажатия кнопки, но и на значение этой переменной. Таким образом тебе не нужно сам обработчик убирать вообще.
JavaScript:
  mp.events.add("render", () => {
    if (mp.keys.isDown(78) === true && viewerAllowed) {
      mp.game.graphics.drawText(...);
    }
  });
Ну либо выкинуть промежуточный renderOn ивент и вешать/убирать обработчик сразу на render
Вот еще вопрос назрел, а не будет плохо, что у игрока всегда будет работать render, который каждый кадр будет проверять условие?🤯
 
Проблема в том, что ты добавляешь обработчик на render внутри другого своего обработчика renderOn. И когда ты убираешь renderOn, то вложенный обработчик уже был проинициализирован и никуда не денется.
Я бы добавил какую-то переменную или свойство игрока в котором менял значение на true|false в зависимости от команды. И был бы просто render обработчик который смотрел не только на статус нажатия кнопки, но и на значение этой переменной. Таким образом тебе не нужно сам обработчик убирать вообще.
JavaScript:
  mp.events.add("render", () => {
    if (mp.keys.isDown(78) === true && viewerAllowed) {
      mp.game.graphics.drawText(...);
    }
  });
Ну либо выкинуть промежуточный renderOn ивент и вешать/убирать обработчик сразу на render

Готово!

Код на сервере:
JavaScript:
mp.events.add({
  playerCommand: (player, command) => {
    const parameters = command.split(/[ ]+/);
    const commandName = parameters[0];
    if (commandName === "viewer") {
      player.getOwnVariable("viewer")
        ? player.setOwnVariable("viewer", false)
        : player.setOwnVariable("viewer", true);
      player.call("viewer_client", [player]);
    }
  },
});

Код на клиенте:
JavaScript:
mp.events.add({
  viewer_client: (player) => {
    if (player.getVariable("viewer")) {
      mp.events.add("render", () => {
        if (mp.keys.isDown(78) === true) {
          mp.game.graphics.drawText(`Нажата кнопка [N]`, [0.5, 0.005], {
            font: 7,
            color: [255, 255, 255, 185],
            scale: [0.5, 0.5],
            outline: false,
          });
        }
      });
      mp.events.call("render");
    } else {
      mp.events.remove("render");
    }
  },
});
 
Можно, при желании, событие render вывести в отдельную функцию, чтобы направить работу remove в более точное русло))

Спасибо Lev Angel!
 
Можно, при желании, событие render вывести в отдельную функцию, чтобы направить работу remove в более точное русло))

Спасибо Lev Angel!
С переменными сущностей, по идее можно еще упростить. Есть встроенный ивент который триггерится на клиенте если их меняешь: https://wiki.rage.mp/index.php?title=Events::addDataHandler

Изменил код на клиенте:

JavaScript:
mp.events.addDataHandler("viewer", function (entity, value) {
  if (entity.type === "player" && value === true) {
    mp.events.add("render", renderOnViewer);
    mp.events.call("render", renderOnViewer);
  } else {
    mp.events.remove("render", renderOnViewer);
  }
});

function renderOnViewer() {
  if (mp.keys.isDown(78) === true) {
    mp.game.graphics.drawText(`Нажата кнопка [N]`, [0.5, 0.005], {
      font: 7,
      color: [255, 255, 255, 185],
      scale: [0.5, 0.5],
      outline: false,
    });
  }
}

Убрал строку из кода на сервере (ныне не нужна:cry:):
JavaScript:
player.call("viewer_client", [player]);
 
Последнее редактирование:
Решение
Назад
Верх