Онлайн-эмоции
В 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)
- Отправитель. Горячая клавиша локального игрока вызывает
PlayerEmotes.Played(то же событие, на которое подписан локальный код).OnlineEmoteRelayподключается к этому событию, пока работает сервис синхронизации мира, и отправляет имя шарика в матч мира только пока сервис запущен, подключён и присоединён к матчу мира. Повторное подключение не приводит к двойной отправке. - Сервер. Матч мира пересылает opcode
3остальным игрокам как есть — так же, как события смены карты (2) и последователя (4). Тело сообщения он не интерпретирует. - Получатель.
WorldSyncServiceстрого разбирает сообщение, вызываетOnPlayerEmote(userId, balloonName), аPlayerSpawnManagerрисует шарик над аватаром этого игрока — если аватар создан, то есть видят его только игроки внутри вашей области интереса.
Сообщение
| Opcode | 3 (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}'.");
Справочник
| Тип | Пространство имён | Роль |
|---|---|---|
OnlineEmotes | OpenMon.MCE.Online.World | Формат сообщения, проверка имени, ShowOver(Transform avatar, string name, EmotionBalloonSet game), событие Shown |
OnlineEmoteRelay | OpenMon.MCE.Online.World | Передаёт PlayerEmotes.Played в сокет |
WorldSyncService | OpenMon.MCE.Online.World | OP_EMOTE, OnPlayerEmote |
PlayerSpawnManager | OpenMon.MCE.Online.World | Рисует шарик над удалённым аватаром |