Перейти к основному содержимому

Онлайн-эмоции

В MCE Online эмоциональные шарики, которые показывает игрок, видят и остальные игроки: нажмите F3, и над вашим аватаром появится сердце на каждом экране, в зону которого вы попали.

Эмоции идут через тот же матч реального времени, что и обновления позиции (см. Синхронизация мира). Им не нужны ни дополнительный сервис, ни RPC, ни база данных: эмоция — это крошечное сообщение, которое ретранслируется и забывается.

Доступно в уровнях Pro и Source.

Поток​

 sender                         Nakama world match                     receiver
────── ────────────────── ────────
F3 pressed
PlayerEmotes.Played("heart")
OnlineEmoteRelay ──opcode 3──▶ relays it as it comes ──opcode 3──▶ WorldSyncService.HandleEmote
{"e":"heart"} (no inspection) OnlineEmotes.TryRead (checks the name)
OnPlayerEmote(userId, "heart")
PlayerSpawnManager.ApplyEmote
OnlineEmotes.ShowOver(avatar, "heart", gameSet)
  1. Отправитель. Горячая клавиша локального игрока вызывает PlayerEmotes.Played (то же событие, на которое подписан локальный код). OnlineEmoteRelay подключается к этому событию, пока работает сервис синхронизации мира, и отправляет имя шарика в матч мира только пока сервис запущен, подключён и присоединён к матчу мира. Повторное подключение не приводит к двойной отправке.
  2. Сервер. Матч мира пересылает opcode 3 остальным игрокам как есть — так же, как события смены карты (2) и последователя (4). Тело сообщения он не интерпретирует.
  3. Получатель. WorldSyncService строго разбирает сообщение, вызывает OnPlayerEmote(userId, balloonName), а PlayerSpawnManager рисует шарик над аватаром этого игрока — если аватар создан, то есть видят его только игроки внутри вашей области интереса.

Сообщение​

Opcode3 (WorldSyncService.OP_EMOTE)
Тело{"e":"heart"} — JSON-объект с именем шарика в поле e
Как собратьOnlineEmotes.Payload(name)

Безопасность: другой участник не может заставить вас что-либо нарисовать​

То, что присылает другой участник, — текст извне, поэтому ему никогда не доверяют:

  • Имя проверяется методом OnlineEmotes.IsValidName до того, как им что-либо воспользуется: строчные буквы, цифры и символы подчёркивания, не более OnlineEmotes.MaxNameLength (32) символов. OnlineEmotes.TryRead(json, out name) возвращает false для всего остального — некорректного JSON, пустого имени, слишком длинного, — а WorldSyncService пишет в лог Bad emote from <user>: not a balloon name. и отбрасывает сообщение.
  • Рисуется всегда шарик с этим именем, который ваша игра или движок уже имеют (EmotionBalloonSet.Resolve). Сообщение несёт имя, но никогда не спрайт. Имя, которого ни у кого нет, ничего не рисует.

Именно поэтому шарикам не нужна синхронизация контента: если ваша игра заменяет heart своим рисунком, каждый игрок вашей игры видит ваше сердце.

Наблюдение за эмоциями​

ЧленКогда
WorldSyncService.OnPlayerEmoteПришла допустимая эмоция: (userId, balloonName)
OnlineEmotes.ShownНад удалённым аватаром нарисован шарик, уже на месте: (balloonName, avatarTransform). Подписчик, выбросивший исключение, записывается в лог и не останавливает шарик.
using OpenMon.MCE.Online.World;

OnlineEmotes.Shown += (name, avatar) =>
Debug.Log($"{avatar.name} shows '{name}'.");

Справочник​

ТипПространство имёнРоль
OnlineEmotesOpenMon.MCE.Online.WorldФормат сообщения, проверка имени, ShowOver(Transform avatar, string name, EmotionBalloonSet game), событие Shown
OnlineEmoteRelayOpenMon.MCE.Online.WorldПередаёт PlayerEmotes.Played в сокет
WorldSyncServiceOpenMon.MCE.Online.WorldOP_EMOTE, OnPlayerEmote
PlayerSpawnManagerOpenMon.MCE.Online.WorldРисует шарик над удалённым аватаром