This is a mobile optimized page that loads fast, if you want to load the real page, click this text.

Проблема object и notifyStreaming

qweqweqwe123123123

Участник портала
24 Июн 2025
57
7
18
Ребят, привет. Немного запутался, подскажите пожалуйста
Эта система инвентаря. Если точнее, игрок выбрасывает предмет на землю.

Логика:

1) СЕРВЕР. Я создаю объект на сервере

Код:
const newDropItem = mp.objects.new(
    mp.joaat(itemData.joaatName),
    new mp.Vector3(p.x, p.y, p.z - Z_OBJECT),
    {
      rotation: ZERO_VECTOR,
      alpha: 255,
      dimension: player.dimension,
    },
  );

2) Прямо объекту присваиваю variable

Код:
newDropItem.setVariable("inv:drop-item:collision", false);

3) Далее ВСЕМ игрокам на карте отправляю событие на клиент, передав туда IDшник созданного объекта на сервере

Код:
mp.players.forEach((user: PlayerMp) => {
    user.call(Inventory["SRV-CLI:enable-stream-in:drop-item"], [
      newDropItem.id,
    ]);
  });

4) КЛИЕНТ. Далее я на клиенте включаю object.notifyStreaming = true; (это нужно для того, чтобы созданный объект на серверной части мог отображаться в ивенте entityStreamIn на клиетнской части).

Код:
addServer(
  Inventory["SRV-CLI:enable-stream-in:drop-item"],
  (remoteObjId: number) => {
    const object = mp.objects.atRemoteId(remoteObjId);
    if (!object) return;
    object.notifyStreaming = true;
  },
);

5) Финал. Также на клиенте я ожидал , что ивент entityStreamIn вызовется и коллизия выключиться.

Код:
mp.events.add("entityStreamIn", (entity: EntityMp) => {
  if (!entity || entity.type !== "object" || entity.handle === 0) {
    return;
  }
  const value = entity.getVariable("inv:drop-item:collision");
  if (typeof value === "boolean") {
    entity.setCollision(value, value);
  }
});

Суть проблемы: когда только сервер запускаю и выбрасываю первый предмет на землю , то пункт 5 (ивент entityStreamIn) - не вызывается (хотя по идеи, если ты делаешь object.notifyStreaming = true, то вызваться должен , я это делаю в пункте 4). Потом еще раз что то выбрасываю из инвентаря - и все работает. Последующие выброшенные вещи дальше -тоже работают. Я также делал задержку до появления handle в пункте 4 (await isLoadedEntity handle), но это не помогло.

В целом логика правильная ? правильно ли я создаю объект, даю ему setVariable, передаю данные, через forEach оповещаю игроков, правильно ли делаю синхронизацию и тд тд ? Как вы это делаете, какие варианты у вас ?
Ну и главный вопрос, почему ивент entityStreamIn не вызывается (при первом выбрасывании) после object.notifyStreaming = true ?


UPDATE:
Вот наглядный пример. Выкинул первый предмет, entityStreamIn не вызвался (после object.notifyStreaming = true) и игрок одной ногой стоит на нем.
Выкинул еще, всё отработало прекрасно и коллизия выключилась.

 
Последнее редактирование:

Jerry (ChatGPT)

AI-powered language model
VIP
helper
17 Окт 2023
2,749
269
100
Привет! Логика в целом правильная, часто так делают. По первой проблеме с entityStreamIn при первом выбросе — возможно, событие не вызывается, потому что объект уже изначально стримится у клиента, и notifyStreaming ставишь слишком поздно. Попробуй ставить notifyStreaming сразу после создания объекта (ещё до передачи ID клиенту), чтобы клиент изначально получал этот флаг. Либо на клиенте перед выставлением notifyStreaming сделай проверку, есть ли объект в стриме уже, и если да — вручную вызови нужный код коллизии.
Ещё проверь, что dimension у объекта и игрока совпадает в момент стрима, иначе объект может не стримиться вовсе.
Если надо — можно также на клиенте кэшировать ID/состояния, и в entityStreamIn делать дополнительные проверки.
В общем, notifyStreaming = true должна ставиться до того, как клиент начинает получать этот объект, иначе событие может не сработать.
Проверь эти моменты, должно помочь.
 

Vermilion

Искусственный Интеллект
High developer
BackEnd developer
FrontEnd developer
29 Сен 2021
1,661
1,033
181
35
В ивенте entityStreamIn поставь не большой тайм аут, перед тем как проверяешь у сущности variable. Она может не прогрузится.
 

XDeveluxe

⚡️BackEnd Developer
Команда форума
Moderator
High developer
BackEnd developer
30 Авг 2021
3,207
1,910
216
28
Либо так, либо добавить mp.events.addDataHandler, в котором проверка по ключу и когда приходит ключ с новым значением переменной - менять коллизию.
 

qweqweqwe123123123

Участник портала
24 Июн 2025
57
7
18
Точно! Забыл блин об этом. Просто это странно у тебя есть уже object, есть у тебя handle у object, и все равно ты не можешь без setTimeout вызывать метод у этого object в entitytStreamIn... Типа все данные есть, handle есть, а методы не работают.
Было ло бы классно не хардкодить 200-350мс, а как то вычислять это динамически... Есть у кого варианты на что завязаться можно в условии ? Вдруг понадобиться в одном случае 50мс, а в другом 150мс или 250мс...


Ого, это интересно.На коленке накидал такой код, но что то не работает,коллизия не выключается
Код:
mp.events.addDataHandler(
  "inv:drop-item:collision",
  function (entity, value, oldValue) {
    if (entity.type === "object") {
      entity.setCollision(value, value);
      (entity as ObjectMp).notifyStreaming = true;
    }
  },
);

UPDATE: повесил await loadEntity(entity) в ивент addDataHandler и вроде завелось... сейчас еще пару тестов сделаю... 10 мин
UPDATE2: да, просто дожидаемся handle у объекта и все работает, который раз уже выручаешь...


И спасибо всем за ответы
 
Последнее редактирование:

Similar threads