AppearanceVisualizer, который указывается на AppearanceComponent. Новый способ — просто использовать компонент для данных, используемых для настройки визуализатора, и систему для фактической логики вместо одного класса. Преимущества в том, что они могут использовать всё, что могут ECS Systems (включая подписки на события, что важно!).
Этот документ объясняет, как мигрировать AppearanceVisualizer на новый компонент и систему, используя базовый пример из этого PR: https://github.com/space-wizards-federation/space-station-14/pull/6571/files с некоторыми очень незначительными отклонениями. Директивы using и тому подобное не будут включены, так что вам нужно будет сделать их самостоятельно.
Вот полный визуализатор, который мы переносим:
1. Разделите данные и логику
Первая задача — скопировать данные в новый компонент и скопировать логику в новую систему. Не беспокойтесь о полном переносе прямо сейчас или об ошибках, мы сделаем это позже. Компонент:2. ECS-ификация данных
Теперь нам нужно преобразовать компонент в надлежащее состояние ECS!- Сделать все приватные поля публичными
- Удалить любые свойства и использовать только поля напрямую; любая логика должна быть в методах-членах системы
- Изменить имена всех полей в соответствии с соглашениями об именовании
- Добавить дополнительные поля данных при необходимости
- Переместить соответствующий enum
VisualLayers, если он существует, также в класс компонента
3. ECS-ификация логики
Логику нужно перенести двумя способами:- Метод
OnAppearanceChangeнеобходимо преобразовать в соответствующее переопределение entity system - Любой метод
InitializeEntityнеобходимо преобразовать в новый обработчик событияComponentInit, направленный на созданный вами компонент
- Все зависимости должны быть перемещены в систему
- Все ручные resolve должны быть преобразованы в зависимости
- Все resolve
IEntityManagerдолжны использовать полеEntityManager, которое уже существует вEntitySystem, или прокси-методы - Все TryGet для
SpriteComponentдолжны использовать полеSpriteв аргументах события - Все ссылки на поля, которые раньше были на визуализаторе, необходимо преобразовать в ссылки на поля компонента
protected override void OnAppearanceChange(EntityUid uid, T component, ref AppearanceChangeEvent args), поэтому мы обновим функцию соответствующим образом.
Нам также нужно удалить resolve IEntityManager и преобразовать вызовы к нему в прокси-методы. Однако, поскольку используемые вызовы методов нужны только для получения SpriteComponent, мы можем использовать поле в аргументах события.
InitializeEntity, но если бы использовал, полный класс выглядел бы так:
4. Обновите YAML и IgnoredComponents.cs
Теперь нам нужно обновить YAML для нашего нового компонента, а также список игнорируемых сервером компонентов. Перейдите вContent.Server/Entry/IgnoredComponents.cs и добавьте строку с именем вашего нового компонента следующим образом:
5. Если возможно, обобщите
Вместо добавления множества отдельных систем и компонентов визуализаторов часто можно сделать визуализатор более общим, добавив дополнительное YAML-поле данных. Для этого существуетGenericVisualizerSystem и компонент, который заменяет старый GenericEnumVisualizer. Если всё, что вам нужно от визуализатора, — это установить некоторые данные слоя спрайта на основе простых записей данных внешнего вида, вы, скорее всего, можете и должны использовать generic visualizer вместо создания собственного. Однако если вам нужно делать что-то необычное, например, использовать анимации или более сложную логику, вам всё равно придётся создавать свой собственный.
Например, функциональность вышеуказанного визуализатора шкафа просто устанавливает состояния и видимость слоя спрайта на основе двух записей данных внешнего вида. Вместо этой системы и компонента та же функциональность может быть достигнута с использованием generic visualizer:
sprite, state, texture, shader, scale, rotation, offset, visible и color.
Обратите внимание, что YAML для значений внешнего вида — это просто результаты ToString() значений данных внешнего вида.
Таким образом, bool становятся “True”/“False”, а enum, такой как VentPumpState.Off, просто становится “Off”.