...
суббота, 17 декабря 2016 г.
Проект CallSharp: I/O Call Instrumentation на платформе .NET
Чтo мнe нpaвитcя вo вcякиx paзpaбoтчecкиx тулax, тaк этo тo, чтo oни нe тoлькo пoмoгaют peшaть кaкиe-тo зaдaчи, нo пopoй eщe и учaт пpoгpaммиpoвaнию. Tулa, пpo кoтopую я xoчу paccкaзaть – oнa имeннo тaкaя. СаllShаrр – тaк нaзывaeтcя мoй пpoeкт – пытaeтcя aлгopитмичecки вывecти цeпoчку вызoвoв нa ocнoвe нaбopa вxoдныx и oжидaeмыx выxoдныx дaнныx.
Cнaчaлa пpocтoй пpимep: у вac ecть "аbс"
"сbа"
Этoт пpимep идeaльнo иллюcтpиpуeт пpoблeму, т.к. в .NЕТ у cтpoки нeту мeтoдa Rеvеrsе()
new string(input.Reverse().ToArray())
Cлeдoвaтeльнo, xoтeлocь бы пoлучить пpoгpaмму, кoтopaя caмa вывoдилa бы эти цeпoчки вызoвoв нa ocнoвe вxoдныx и выxoдныx дaнныx, гуляя пo .NЕТ ВСL АРI, дeлaя вce вoзмнoжныe вызoвы и пpoвepяя иx нa cooтвeтcтвиe. Звучит нeмнoгo фaнтacтичнo, дa?
Дaвaйтe вoзьмeм для нaчaлa пpocтoй пpимep:
B нaшeм cлучae аbс
аbс
АВС
Haм пoвeзлo чтo cтpoки в .NЕТ нeмутaбeльны, и нaм нe нужнo пpoвepять измeнeния opигинaльнoй cтpoки пocлe вызoвoв нa нeй – тoлькo выxoднoгo знaчeния. A cлeдoвaтeльнo, мы мoжeм взять и пoиcкaть вce мeтoды (a тaкжe cвoйcтвa, кoтopыe в .NЕТ тoжe мeтoды c пpиcтaвкoй gеt_
-
Являютcя нecтaтичecкими мeтoдaми клacca
(string
, ecли быть пeдaнтичными)Systеm.String
-
Moгут нe пpинимaть ни oднoгo apгумeнтa
-
Boзвpaщaют cтpoку
Пpимeчaтeльнo, чтo «мoгут нe пpинимaть ни oднoгo apгумeнтa» – этo тpи paздeльныx cлучaя, a имeннo
-
Функция нe имeeт пapaмeтpoв вooбщe, т.e.
Fоо()
-
Функция мoжeт и имeeт пapaмeтpы, нo у вcex ниx ecть дeфoлтныe знaчeния, т.e.
Fоо(int n = 0)
-
Функция бepeт упaкoвaный cпиcoк, т.e.
Fоо(раrаms сhаr[] lеttеrs)
Ecли pукoвoдcтвoвaтьcя этими кpитepиями, мы пoлучим cпиcoк фунций string
"аbс"
Normalize
ToLower
ToLowerInvariant
ToUpper
ToUpperInvariant
ToString
Trim
TrimStart
TrimEnd
Бepeм кaждую из этиx функций, вызывaeм нa "аbс"
input.ToUpper()
input.ToUpperInvariant()
Уpa, пepвaя миccия выпoлнeнa!
Kaк пoнять, чтo зa тип у чиcлa 3 cпpaвa? Я пpeдлaгaю вoт тaкoй aлгopитм:
-
Чepeз rеflесtiоn, бepeм вce типы у кoтopыx ecть мeтoд
.ТryРаrsе()
-
Bызывaeм нa вcex дaнныx. Ecли вoзвpaщaeт
– дeлaeм бoкcинг pacпapшeннoгo (нeoлoгизм?) oбъeктa, вoзвpaщaя eгo кaкtruе
.оbjесt
-
He зaбывaeм, чтo любoй ввoд этo кaк минимум
. A ecли ввoд имeeт длину 1, тo этo eщe иstring
.сhаr
Coглacнo этoму aлгopитму, тpoйкa (3) cпpaвa мoжeт быть и string
сhаr
flоаt
ТimеSраn
Int32
int
Иcпoльзуя вce тoт жe линeйный пoиcк пo нecтaтичecким мeтoдaм, мы мoмeнтaльнo нaxoдим
input.Length
Ecтecтвeннo, чтo нa caмoм дeлe этo вызoв функции gеt_Lеngth()
Читepcкий пpимep. Ecли бы я взял truе
IsNоrmаlizеd()
-
He oбязaтeльнo являютcя члeнaми клacca (в нaшeм cлучae – cтpoки), нo тeм нe мeнee пoпaдaют в cпиcoк oдoбpeнныx типoв. Пpичинa: я нe xoчу пpoизвoльнo вызывaть
, нaпpимepFilе.Dеlеtе()
-
Boзвpaщaют нужный нaм тип (в дaннoм cлучae –
)bооl
Pacшиpив нaш пoиcк дo cтaтики, мы пoлучили двa впoлнe кoppeктныx peзультaтa:
string.IsNullOrEmpty(input)
string.IsNullOrWhiteSpace(input)
Пpeкpacнo! Дaвaйтe чтo-нибудь пocлoжнee ужe!
Уxx, тут cитуaция пocлoжнee – "аbс "
string
string
string
string
чтo угoднo
string
Имeннo нa этoм этaпe пpoиcxoдит кoмбинaтopный взpыв. Hу, a чтo вы xoтeли? Зaтo мы нa нaшиx вxoдныx дaнныx пoлучaeм oчeнь мнoгo вapиaнтoв:
string.Concat(input.Split()).ToUpper()
string.Concat(input.Split()).ToUpperInvariant()
input.ToUpper().Trim()
input.ToUpper().TrimEnd()
input.ToUpperInvariant().Trim()
input.ToUpperInvariant().TrimEnd()
input.Trim().ToUpper()
input.Trim().ToUpperInvariant()
input.TrimEnd().ToUpperInvariant()
input.TrimEnd().ToUpper() // + lots more solutions
Я нe cтaл выклaдывaть вce peшeния, иx дocтaтoчнo мнoгo. Kaк видитe, вce вapиaнты являютcя бoлee-мeнee пpaвильными, нo нe учтeнa кoммутaтивнocть вызoвoв: вeдь пo cути нe вaжнo, вызывaть нaм .Тrim().ТоUрреr()
.ТоUрреr().Тrim()
Этo нe ужacнaя пpoблeмa кoгдa вызoвoв 2, нo кoгдa иx 3 или бoльшe, кoличecтвo излишнeй paбoты, кoтopую вынуждeнa дeлaть пpoгpaммa, вecьмa внушитeльнo.
Mы пoкa чтo oбcуждaли тoлькo «няшныe» функции кoтopыe мoжнo вызывaть бeз apгумeнтoв. Bcё – тaкoe дeлo бoльшe нe пpoкaтит. Чтoбы удaлить bbb
b
bbb
Ecтecтвeннo, чтo вce apгумeнты вызoвa дoлжны кaк-тo кoppeлиpoвaть c oбъeктoм, нa кoтopoм идeт вызoв. Для этoгo cдeлaн cтpaшный и ужacный FrаgmеntаtiоnЕnginе
Дaвaйтe вoзьмeм cтpoку аааbbb
-
Bce вoзмoджныe буквы (в дaннoм cлучae –
и'а'
)'b'
-
Bce вoзмoжныe пoдcтpoки (в т.ч. пуcтaя cтpoкa). Этo peaльнo бoлeзнeннaя oпepaция, т.к. нa длиннoй cтpoкe иx oчeнь мнoгo.
-
Bce вoзмoжныe чиcлa в пpeдeлax длины caмoй cтpoки. Этo нужнo для вызoвoв вcякиx
.Substring()
Haдpoбив cтpoку нa вcякиe oбъeкты, мы ищeм мeтoды – cтaтичecкиe или нeт – кoтopыe бepут эти oбъeкты. Tут вce бoлee мeнee пpeдcкaзуeмo, зa иключeниeм тoгo чтo
-
Bызoвы c 2+ apгумeнтами дeлaют нexилый кoмбинaтopный взpыв. Пpocтoй пpимep – этo
.Substring()
-
Bызoвы функций кoтopыe бepут
тeopeтичecки coздaют ничeм нe oгpaничeнный кoмбинaтopный взpыв, пoэтoму иx нужнo или лимитиpoвaть или нe вызывaть вooбщe.раrаms[]
СаllShаrр, кoнeчнo, cпpaвляeтcя c нaшим cинтeтичecким пpимepoм и выдaeт нaм
input.Trim('b')
input.TrimEnd('b')
Kaк вы ужe нaвepнoe дoгaдaлиcь, кoмбинaтopныe взpывы мoгут пoднaбpocить нa вeнтилятop oчeнь мнoгo вapиантoв кoтopыe, будучи кoppeктными, являютcя излишнe cлoжными. Boт нaпpимep:
Xмм, кaзaлocь бы, нужнo вceгo лишь удaлить еr
е
r
input.Trim('e','r')
input.Trim('r','e')
input.Trim('a','e','r')
input.Trim('a','r','e')
input.Trim('e','a','r')
input.Trim('e','r','a')
input.Trim('r','a','e')
input.Trim('r','e','a')
input.TrimEnd('e','r')
input.TrimEnd('r','e')
// 30+ more options
Kaк видитe, пepвыe двa вapиaнтa – eдинcтвeнныe, кoтopыe xoтeлocь бы иcпoльзoвaть. Bce ocтaльныe oблaдaют излишнeй инфopмaциeй, кoтopaя нe дeлaeт никoму пoгoды. Или вoт eщe
Tут вapиaнтoв мeньшe, вoт oни:
input.Replace("aabb", "aa")
input.Replace("bb", "")
input.Replace("bbcc", "cc")
Eдинcтвeннaя пpaвильнaя oпция вышe – cpeдняя. Двe дpугиe xoть и кoppeктны c тoчки зpeния ceмaнтики, вce жe – cкopee вceгo нe тo, чeгo мы xoтeли дoбитьcя.
Eщe oднo интepecнoe нaблюдeниe – этo тo, чтo инoгдa интepecныe peшeния кpoютcя нa глубинe, a нe нa пoвepxнocти. Boт нaпpимep
Tут мoжнo пpocтo удaлить пpoбeл, нo СаllShаrр дaeт мнoгo вapиaнтoв, нaпpимep
input.Replace(" ", string.Empty)
input.Replace(" b ", "b")
input.Replace("a b ", "ab")
input.Replace(" b c", "bc")
input.Replace("a b c", "abc")
// at greater depth,
string.Concat(input.Split())
Лучшиe вapиaнты – пepвый и, вoзмoжнo, пocлeдний – oн xoть и пoдopoжe c тoчки зpeния выпoлнeния (нaвepнoe, нe пpoвepял, интуиция пoдcкaзывaeт), нo выглядит элeгaнтнo. Этo xopoший пpимep тoгo, кaк пpoгpaммa мoжeт вывecти тo, чтo чeлoвeк cpaзу нe увидит.
Peзюмиpуя
Ceйчac СаllShаrр paбoтaeт, cкaжeм тaк, нeбыcтpo. Пpoблeмa в ocнoвнoм в иcпoльзoвaнии reflection (в чacтнocти, МеthоdInfо.Invоkе()
Teкущиe пpoблeмы c пepфopмaнcoм oтчacти peшaтcя при пepeeздe oт динaмичecкoгo дo cтaтичecкoгo rеflесtiоn (пpeдпoлaгaeтcя cдeлaть вcё нa Т4). Oптимизaций мoжнo дeлaть oчeнь мнoгo – я бы нaпpимep xoтeл cдeлaть aннoтaции для paзмeтки «кoммутaтивнocти» кaк нaбopoв функций, тaк и apгумeнтoв в функцияx (нaпpимep, пopядoк букв в Тrim()
СаllShаrр – ореn sоurсе пpoeкт, лежит на GitHub. Taм жe ecть eгo релизы – пo ccылкe click here уcтaнoвитcя СliсkОnсе диcтpибутив, кoтopыe caмooбнoвляeтcя пo мepe выxoдa нoвыx вepcий.
Для тех, кому хочется чуть более живого повествования, ниже представлен мой доклад на Петербургской .NET User Group:
Cпacибo зa внимaниe!
Создание инструментов для исследования NES-игр
Большая часть того, что необходимо исследователю, уже есть в эмуляторе FCEUX, который хорошо подходит для отладки игр. В документации стоит досконально изучить раздел Debug, каждый инструмент оттуда полезен исследователю, причём умение использовать их совместно друг с другом усиливает возможности хакера.
Однако я не буду пересказывать документацию, а остановлюсь на случаях, когда возможностей эмулятора оказывается мало и необходимо добавить новые, либо же когда существуют необычные способы найти желаемое в ROM-файле напрямую, в обход длительного изучения кода игр.
Использование Lua-скриптов
Собственно, первый способ, пример которого приведён на картинке для привлечения внимания – создание вспомогательных инструментов с помощью встроенного в эмулятор интерпретатора Lua-скрипт.
На примере выше для исследования игры (и просто читерского прохождения, при желании) используется такая возможность скриптов, как вывод изображений на экран поверх отрисовываемой эмулятором картинки.
Таким образом исследователь может заметить то, что недоступно обычному игроку, например, на скриншоте выше из трёх скрытых бриллиантов игрок может допрыгнуть только до первых двух, и никаким образом не может взять третий или даже просто догадаться об его существовании. В «Утиных историях 2» встречаются даже такие драгоценности, которые вообще размещены за пределами игрового уровня.
Другой пример скрипта с выводом на экран дополнительных данных – компас до ближайшего драгоценного камня в «Книге Джунглей»:
Естественно, визуализация информации из оперативной памяти или ROM игры не единственная возможность скриптов.
Другая часто используемая возможность – логгирование происходящего в коде игры, например, шаблон скрипта для дампа разархивированных данных сразу после их распаковки (для SMD игр, но принцип применим и для NES).
Ну, и никто не запрещает создание на Lua-скриптах полноценных утилит, вроде уже включённого в эмулятор редактора нажатых клавиш TasEditor.
Также, на мой взгляд, недооцененной является идея частичного переписывания кода игры на скриптах, когда игровые данные патчатся скриптом на лету для модификации геймплея. Proof-of-concept такого скрипта, модифицирующего врагов в «New Ghostbusters 2»:
Однако, для сложной обработки конкретной игры или создания новых методов хака стоит задуматься об использовании следующего метода.
Модификация исходного кода эмулятора
Здесь есть где разгуляться фантазии на разные темы, не касающиеся исследования игр, вроде добавления в эмуляторы поддержки достижений, 3d-рендера или улучшенной графики, однако я попытаюсь удержаться в рамках темы статьи.
Одно из направлений расширения эмулятора с целью улучшения возможностей для реверс-инженерии – прокидывание как можно большего числа его внутренних возможностей в Lua-библиотеки. Во второй статье цикла я уже показывал, как с помощью прокидывания всего пары новых функций появилась возможность сделать универсальный (подходящий для исследования любой игры) инструмент для исследования.
Другой простой и полезный пример, который пока ещё отсутствует в последней версии эмулятора – возможность модификации из скрипта памяти PPU.
Модификация эмулятора может также использоваться для того, чтобы встроить в него редактор для конкретной игры с возможностью на лету запустить её и проверить внесённые изменения:
Скрипты для статического анализа кода игры
Предыдущие две категории модификаций касались динамического анализа игры в ходе её выполнения. Однако большая часть исследования – это статический анализ ROM-файла игры (или дампов каких-либо данных из него).
Основной программой для такого анализа кода является интерактивный дизассемблер IDA. Он поддерживает ассемблер 6502, однако требует как плагина для правильной загрузки файлов в формате nes, так и набора скриптов для автоматизации рутинных действий по преобразованию загруженного файла в причёсанный код. Набор скриптов, специфичных для исследования NES-игр собран тут.
Сами скрипты для IDA могут быть написаны на встроенном языке команд idc или python, в любом случае лучше всего открыть их текстовым редактором и изучить, в большинстве случаев это помогает лучше понять команды самого IDA, которые пригодятся в работе с ним и научиться писать такие скрипты самому. Это очень пригодится, когда понадобится провести несколько сотен однотипных действий, вроде объединения байт в поинтеры или выделения массивов по некоторым правилам.
Инструменты для статического анализа данных игры
IDA хороший инструмент для анализа кода, настолько хороший, что некоторые гуру исследования игр даже считают, что только его достаточно для исследования и изменения игр. Однако, даже имея на руках разобранную до компилируемых и прокомментированных исходников игру, сложно модифицировать игровые данные – уровни, графические карты, анимации персонажей. К сожалению, формат игровых данных часто сильно отличается от игры к игре, поэтому создать универсальные инструменты, подходящие для большинства игр, достаточно трудно.
Редакторы тайловых карт
Формат хранения графических банков (самый низкий уровень хранения графики) стандартный для всех игр NES, поэтому существует множество редакторов тайловых карт, однако, среди них я не нашёл ни одной библиотеки, которая позволяла бы рендерить эти тайлы в своём приложении.
Такими программами можно редактировать тайлы графики в играх с наличием CHR-ROM – целыми банками графики. В других играх используется CHR-RAM – видеопамять тайлов в них считывается частями из банка с данными и кодом и копируется в видеопамять (при этом иногда достаточно хитрыми способами, но о них скорее лучше рассказывать в статье о компрессии данных).
На более высоком уровне игры отличаются уже настолько, что общих программ для редактирования практически нет, максимум существуют редакторы, охватывающие несколько игр на одном движке. Про свои попытки сделать универсальный редактор уровней я напишу в конце статьи, пока же приведу ещё несколько общих идей, как находить данные в играх, и утилит, реализующих эти идеи.
В качестве языка реализации я использую python за то, что на нём можно быстро и просто проверить какую-либо догадку, иногда даже прямо в интерактивном режиме.
Коррапт ROM
Собственно, как раз про эту идею была вторая статья цикла – если перебрать все возможные варианты изменения одного байта в ROM и посмотреть, как это отразится на экране, то это может помочь прояснить внутреннюю структуру игры. После этого возможно даже составить простой вариант редактора игры – нужно заготовить набор картинок-блоков верхнего уровня, из которых строится экран, не вникая до конца, как строятся сами эти картинки из данных ROM и отобразить массив этих картинок, обнаруженный этим методом.
Поиск блоков
Можно также зайти с другой стороны.
Фон, который отображается на экране, задаётся массивом индексов тайлов видеопамяти по фиксированному адресу PPU – для NES существует 4 экранные страницы, которые в зависимости от настроек PPU могут разными способами выводится на экран. Не важно, что именно будет на экране, достаточно просто захватить какую-нибудь загруженную страницу для анализа.
Первая экранная страница (Name Table) расположена по адресам PPU $2000-$23BF.
Её содержимое в эмуляторе FCEUX можно посмотреть в окне Debug -> Name Table Viewer:
А также в виде байт в окне Debug -> Hex Editor, View -> PPU Memory (перейти по адресу $2000).
Здесь же можно сделать дамп всей видеопамяти, который пригодится нам для анализа (File->Dump to File->PPU Memory).
Это просто массив из 960 индексов маленьких тайлов видеопамяти размером 8x8 пикселей. При этом, после реверса большого числа игр известно, что игровые экраны часто описываются блоками большего размера, например, 16x16 или 32x32 пикселей. Таким образом, если мы предположим некоторый размер блока (для начала попробуем самые стандартные – 2x2 тайла, выделены на скриншоте красной рамкой), то мы можем разбить данные из экранной страницы на участки, в каждом из которых окажется описание одного блока.
Так получается список из всех блоков, которые присутствуют на экране. Причём у нас «чистые» описания блоков, без информации о спрайтах персонажей (спрайты рисуются другим способом), и независимый от анимации (анимации фона практически всегда делаются с помощью изменений палитры либо самой видеопамяти, номера тайлов в Name Table остаются неизменными). Однако мы не знаем номера блоков.
У нас есть описание блоков на экране, но мы не знаем их порядок хранения в ROM. Тем не менее, мы можем с некоторой вероятностью предположить, где именно расположено описание блоков. Алгоритм для этого такой:
1. Проходим по всему ROM и размечаем все адреса, по которым обнаруживается какой-нибудь блок, при этом сохраняем его номер (настоящий номер может быть другой, нам важно отметить только отличия блоков друг от друга).
2. Находим область в ROM, в которой обнаружено наибольшее количество РАЗНЫХ блоков. С наибольшей вероятностью именно это и есть описание блоков.
http://ift.tt/2gKmxgC
Таким образом, мы можем найти блоки размером 2x2 в играх, в которых они хранятся последовательно.
Это уже неплохо, но есть способ кардинально улучшить результаты работы алгоритма. Дело в том, что существует ограниченное количество основных размеров блоков и способов их хранения в ROM, и мы можем перебрать их все.
Основные размеры блоков: 2x2, 4x2, 2x4 и 4x4, но в случае необходимости легко добавить и другие размеры.
Со способом хранения их в ROM немного хитрее, блоки могут храниться как линейно, так и разбитыми на части массивами (Structure of Arrays, сокращенно SoA ), т.е. сначала в ROM хранится массив только первых частей блоков, за ним — массивы со следующими частями. Чаще всего такие массивы хранятся друг за другом, при этом промежуток между началами массивов равен количеству блоков. Чтобы найти в ROM такие SoA-массивы, мы должны узнать их длину, что можно сделать перебором всех вариантов (частенько в играх используется по 256 блоков, так что начинать проверку стоит с этого числа и постепенно его уменьшать).
Всё это выглядит достаточно запутанно, ведь мы опираемся только на вероятность того, что игра использует определённый вид блоков, но на практике утилита находит блоки в 80-90% проверенных игр!
Вдобавок, она позволяет отсеять игры с необычной структурой (неблочной), чтобы пристальнее их изучить.
Сравнение CDL-файлов
Эмулятор FCEUX умеет в ходе эмуляции каждую инструкцию отмечать, какие байты были интерпретированы как код, а какие – как данные (меню Debug -> Code/Data Logger...). Эта фича полезна сама по себе и тесно интегрирована с другими отладочными возможностями эмулятора – попробуйте включить этот режим и посмотреть, как изменились другие отладочные окна. Однако, я хочу рассказать об её одном частном применении. Если сохранить два таких cdl-файла, один ДО совершения изучаемого действия, а другой сразу же ПОСЛЕ его окончания, то разница между двумя такими файлами покажет только те данные (или код), которые были использованы во время совершения действия. При грамотном отсечении можно найти нужные данные, всего лишь правильно выбрав два момента времени между измеряемыми событиями.
Формат файла достаточно прост, как и скрипт сравнения, но пользы он может принести очень много, на нём вообще можно построить отдельную методологию отладки.
Компрессоры/Декомпрессоры
Эту тему невозможно раскрыть в паре абзацев, да и она будет слишком упрощённой в контексте только NES-игр, поэтому она заслуживает отдельной статьи.
Универсальный редактор уровней CadEditor
Собственно, изначально эта программа создавалась для отображения уровней в игре «Chip & Dale» (Chip And Dale Editor), дальше по просьбам она была переделана в редактор и со временем обрастали поддержкой других игр Capcom («Darkwing Duck», «Duck Tales 1-2», «Tale Spin», «Little Mermaid»).
Позже выяснилось также, что принципы блочного построения уровней в этих играх очень похожи на способы организации уровней из многих других игр, однако дьявол кроется в деталях – мелкие отличия в каждой игре требуют описывать внутренние структуры редактора максимально гибко, чтобы с помощью комбинаций этих структур можно было описать формат уровней для игр, для которых он изначально не предназначался, без изменения ядра самого редактора.
Фича, с помощью которой обеспечивается универсальность редактора – так называемые конфиги игр. Это скриптовые файлы на языке C#, в которых описано, как именно загружать данные конкретной игры. Почему именно C#? Редактор уже был написан на этом языке и это позволило легко переносить код из ядра в конфиги, не меняя его, что пришлось бы делать, если бы использовался более классический скриптовый язык, вроде Lua.
Использование полноценного языка вместо простого файла настроек позволяет описывать в конфигах свои функции загрузки и сохранения данных любой требуемой сложности. Скрипты представляют собой обычные текстовые файлы, что позволяет пользователям в случае необходимости создавать свой конфиги без перекомпиляции редактора, используя уже существующие конфиги в качестве шаблонов. В комплекте с редактором идут около 500 конфигов для 60 разных игр, около 100 из них сделаны пользователями редактора без моего участия, для игр, в некоторые из которых я даже никогда не играл:
Однако в данный момент, несмотря на попытки сделать универсальный редактор, обнаруживаются игры, которые невозможно описать без модификации самого редактора (тем не менее, множество игр уже можно добавить и так). Чтобы собирать информацию о таких играх с необычной структурой, я пошёл ещё немного дальше и начал использовать сам редактор как библиотеку для Python, чтобы исследовать формат игр перед добавлением их в редактор и тестировать правильность понимания построения уровня конкретной игры. Я реализовал это в виде блокнотов Jupyter, из-за того, что в них удобно как писать код в интерактивном режиме, так документировать его.
http://ift.tt/2hQ9hfo
Составление из базовых тайлов больших игровых структур и сборка в итоге целого уровня напоминает сборку пазла из тысяч кусочков, и доставляет такое же удовольствие, когда, наконец, каждый кусочек оказывается на своём месте.
В следующей статье не будет такого обилия технической информации и я приведу примеры сборки уровней игр с нестандартной структурой или использованием необычных модификаций стандартной блочной архитектуры. Также вы можете в комментариях назвать игру на NES, формат уровней которой интересен вам, возможно, я исследую и её тоже.
Комментарии (0)
Swagger в Magento 2
Тенденция перехода от сборки HTML-страниц на стороне сервера к их сборке на стороне клиента уже даже не тенденция, а тренд. Magento 2, шагая в ногу со временем в меру своих возможностей, также пытается быть в тренде, разнося обработку данных и их представление. Как простому разработчику заглянуть в "чистые" данные, если их представление вынесено достаточно далеко? Есть множество других хороших решений (начиная c tcpdump), и есть swagger.
Swagger достаточно хорошо интегрирован в Magento 2 (если только вам в голову не пришла дурацкая затея изменить код для "default" витрины). Все, что нужно для того, чтобы начать разглядывать "чистые" данные в Magento 2 с точки зрения удаленного приложения — использовать интегрированный в нее Swagger. В данном материале я не рассматриваю особенности использования самого Swagger'а, а просто привожу пример того, как использовать Swagger, интегрированный в Magneto 2, в режиме анонимного пользователя и в режиме аутентифицированного пользователя.
Доступ к сервисам
Я развернул простой Magento-модуль по адресу http://ift.tt/2hCig3x. Чтобы начать использовать Swagger в режиме анонимного пользователя нужно перейти по адресу http://ift.tt/2hFT88Y Сначала загружается само Swagger-приложение (быстро), а затем идет загрузка описания web-сервисов, реализованных в Magento (медленно):
JSON-схему сервисов Magento можно вытянуть и самому по ссылке: http://ift.tt/2hFRi8j
Анонимные запросы
После разбора схемы Swagger формирует список сервисов, доступных анонимному клиенту:
и позволяет не только изучать в человекочитаемом виде сами сервисы:
… но и формировать запросы:
… и анализировать ответы:
Доступ к ограниченным сервисам
Для начала нужно сделать в Magento отдельного пользователя (использовать административную учетку для доступа к сервисам — не самая хорошая идея):
и назначить ей права доступа (User Roles):
Вернее, сначала делается роль, а потом, при создании, она назначается новому пользователю. Предоставлять все права через роль — тоже не самая хорошая идея, но ведь и я не идеален. Поэтому в нашем примере пользователю "swagger" назначена роль "Swagger", которой предоставлены права на доступ к любым ресурсам.
Аутентификация через web-интерфейс не предусмотрена, может быть когда-нибудь кто-нибудь и допилит этот момент в Magento 2, но пока что аутентифицироваться приходится вручную: через свой любимый универсальный REST API клиент, через программный код или через "curl":
curl -X POST "http://ift.tt/2hHrLLO" \
-H "Content-Type:application/json" \
-d '{"username":"swagger", "password":"0jul4san0lRLKjYQpCqx"}'
Все, что нужно сделать — отправить определенный JSON-текст с параметрами аутентификации на определенный адрес (не забыв про заголовок с типом содержимого запроса). В ответ придет сессионный код для доступа к ограниченным сервисам:
"f6j0arlp29vx8i3av9l3eu5sag2pb5qy"
Код придет в кавычках, но использовать его нужно без.
Ну вот, теперь, имея код, мы вводим его в соответствующее поле:
… и получаем доступ к уже более широкому списку сервисов. Например, к такому:
Дальнейшая работа с сервисами ничем не отличается от работы в режиме анонимного пользователя. Сессионный ключ для авторизации добавляется Swagger'ом автоматически:
Заключение
Swagger — замечательный инструмент, замечательно интегрированный в замечательную платформу Magento 2. Разрабатывать web-сервисы с таким инструментарием — одно удовольствие.
Комментарии (0)
пятница, 16 декабря 2016 г.
Security Week 50: социализация криптолокеров, аудит OpenVPN, уязвимость в ядре Linux
Но главной особенностью трояна является альтернативный вариант расшифровки: жертве предлагается отправить друзьям ссылку, по которой, предположительно, скачивается такой же троян, и в случае если два адресата установят вредоносную программу, ключ отправителю будет предоставлен бесплатно (иначе требуют 1 BTC). Предположительно, так как сайт в сети Tor на момент анализа вредоносной программы был недоступен.
В общем, на практике конкретно эта схема работать вряд ли будет. Не стоит забывать и о том, что распространение вредоносных программ преследуется уголовным кодексом вне зависимости от намерений или необходимости срочно расшифровать рабочие документы. Но попытка интересная: дистрибуция вредоносного контента самими жертвами происходит часто, но жертвы обычно об этом не догадываются. А тут дилемма покруче, чем «платить или не платить выкуп». Очень хочется верить в то, что данная технология развития не получит.
Требование выкупа выглядит примерно так. Очень много букв.
Собраны средства на публичный аудит OpenVPN
Новость.
Известный специалист по криптографии Мэтью Грин проведет аудит ПО OpenVPN. Договоренность с Грином достигнута публичным VPN-сервисом Private Internet Access, который спонсирует работу. Примечательно, что 22 ноября сбор средств для такой же цели начал фонд Open Source Technology Improvement. После того, как было собрано более 30 тысяч долларов (в основном жертвовали другие VPN-сервисы), Private Internet Access совершил демарш и оплатил все из своего кармана.
Понятно, что операторы VPN-сервисов кровно заинтересованы как в надежности своих продуктов, так и в грамотном пиаре. Пока непонятно, как разрулится эта ситуация, но если аудита в итоге будет два, никто особо не расстроится. Грин планирует исследовать самую свежую версию OpenVPN 2.4, сейчас находящуюся в стадии Release Candidate, релиз ожидается в январе. Результаты аудита будут «в начале года», хотя, если судить по опыту аудита TrueCrypt, история может затянуться. Напомню, проверка TrueCrypt завершилась в прошлом году: была обнаружена пара мелких уязвимостей, но ни одна не затрагивает защищенность данных.
Закрыта уязвимость в ядре Linux
Новость. Описание и Proof of Concept. Коммит, исправляющий проблему.
Уязвимость, способная привести к локальному повышению привилегий, была обнаружена в модуле af_packet, и появилась она там достаточно давно — в августе 2011 года. Тем не менее, закрыта она была через 4 дня после того, как исследователь приватно зарепортил проблему. В proof of concept показано, как можно создать состояние гонки, и на примере Ubuntu 16.04 с ядром 4.4 был продемонстрирован запуск шелла с правами суперпользователя. Помимо десктопных устройств на Linux, проблема актуальна и для Android, с рядом ограничений. В ряде случаев эксплойт может вызвать зависание системы, а кроме того может быть использован для удаленного взлома сервера, в случае если до этого как-то удалось получить к нему доступ с ограниченными правами.
Что еще произошло:
Серьезная уязвимость в некоторых роутерах Netgear, эксплуатируется тривиально — достаточно кликнуть на подготовленную ссылку, находясь в локальной сети. Временно лечится выключением веб-интерфейса (что тоже можно сделать, кликнув подготовленную ссылку).
Интересное исследование майнинга новой криптовалюты Zcash на чужих мощностях, без ведома владельца. Интересен способ обнаружения: сам майнер де-факто вредоносной программой не является. Но выявить потенциально зараженные системы можно по правилу: «есть майнер, который притворяется другой программой».
Древности
Семейство «Azusa»
Очень опасные вирусы. Поражают Boot-секторы дискет и MBR винчестера. Boot-сектор сохраняют в последнем секторе дискеты, исходный MBR не сохраняют (содержат загрузчик в своем коде). Периодически «завешивают» COM- и LPT-порты. Перехватывают int 13h.
Цитата по книге «Компьютерные вирусы в MS-DOS» Евгения Касперского. 1992 год. Страницa 95.
Disclaimer: Данная колонка отражает лишь частное мнение ее автора. Оно может совпадать с позицией компании «Лаборатория Касперского», а может и не совпадать. Тут уж как повезет.
Комментарии (0)
Боремся с нагрузками в HPE Vertica
В HPE Vertica для планирования работы сервера под нагрузками разработан специальный механизм, под названием «ресурсные пулы». Идея его в том, что каждый пользователь сервера работает в рамках выделенного ресурсного пула, который регулирует приоритетность доступа к ресурсам кластера, ограничивает конкурентность выполнения запросов и описывает правила резервирования и работы с памятью сервера.
По умолчанию после установки сервера Vertica на созданной базе данных это выглядит примерно так:
На каждом сервере (ноде) кластера доступная для Vertica память обозначается, как ресурсный пул General. Для различных нужд сервера автоматически создаются служебные пулы, которые отрезают от General для себя кусочки памяти:
- WOS — для хранения в области памяти порционно вставляемых данных
- TM — для фонового служебного процесса Tuple Mover, выполняющего moveoute и mergeout операции
- Прочие служебные — Vertica имеет дополнительные ресурсные пулы для проведения операций восстановления нод кластера, построения проекций, выполнения служебных запросов и т.д.
По умолчанию пользователи сервера крутятся под управлением самого пула General. Можно посмотреть его текущие настройки:
dbadmin=> SELECT * FROM resource_pools WHERE name = 'general';
-[ RECORD 1 ]------------+------------------
pool_id | 45035996273721212
name | general
is_internal | t
memorysize |
maxmemorysize | 30G
executionparallelism | AUTO
priority | 0
runtimepriority | MEDIUM
runtimeprioritythreshold | 2
queuetimeout | 00:05
plannedconcurrency | 10
maxconcurrency | 20
runtimecap |
singleinitiator | f
cpuaffinityset |
cpuaffinitymode | ANY
cascadeto |
Расшифрую некоторые параметры:
- memorysize — размер зарезервированной памяти пула, этот размер отрезается от пула General, уменьшая его размер доступной памяти, для General соответственно не указывается.
- maxmemorysize — максимально разрешенный размер использования памяти пулом. В случае использования пулом памяти, более указанной memorysize, недостающая память временно забирается из пула General, если там есть конечно что забирать.
- plannedconcurrency — делитель для установки размера памяти, выделяемой сессии при старте запроса в пуле, в данном случае для пула General maxmemorysize: 30 гб делить 10 plannedconcurrency = каждой сессии при старте выделяется 3 гб памяти пула, что мягко говоря жирновато.
- maxconcurrency — максимальное количество выполняемых на пуле конкурентных сессий.
Такие «дефолтные» настройки дают фактически 100% гарантию тормозов работы Vertica:
- 10 сессий запускает выполнение запросов
- каждой сессии выделяется по 3 гб памяти пула, даже если столько и не нужно
- Если сессии еще не успели отработать и новые сессии запустили еще запросы, то вместо памяти из 30 гб они получают работу в свапе
- Если какая-то сессия в ходе работ съела всю память пула, то другие сессии так же оказываются в свапе
Давайте поможем «горю»:
ALTER RESOURCE POOL general PLANNEDCONCURRENCY 20 MAXCONCURRENCY 10;
Теперь каждой сессии при старте запроса в пуле выделяется 0.5 гб, а всего одновременно может выполнятся не более 10 сессий. При старте 10 сессий будет израсходовано 5 гб памяти пула, еще 25 гб останется как резерв для отдачи памяти тяжелым запросам и другим ресурсным пулам.
Хочу обратить внимание на параметр MAXCONCURRENCY — чем он ниже, тем быстрее будут работать ваши запросы. У каждой аппаратной части есть предел нагрузок, при превышении которого все «встает колом». Чем выше конкурентность, тем больше нагрузка на процессоры и дисковые массивы, тем ниже их скорость работы. Эффективнее выполнить 10 запросов и далее с очереди выполнить следующие 10 запросов, чем пытаться выполнить одновременно 20 запросов. Естественно, MAXCONCURRENCY будет в первую очередь зависеть от поставленных для решения задач пула и от характеристик железа кластера, Ваша задача выявить пределы и выставить его чуть ниже пределов, чтобы в случае пиковых нагрузок одновременного выполнения множества тяжелых запросов, кластер вдруг не затормозил для всех его пользователей.
Так что же с пулами? Пока мы только настроили General, однако держать в нем пользователей на самом деле дурная практика. Давайте сделаем типовые пулы по группам задач пользователей:
-- Пул для писателей
CREATE RESOURCE POOL writers
MEMORYSIZE '2G'
MAXMEMORYSIZE '10G'
PLANNEDCONCURRENCY 10
MAXCONCURRENCY 10
PRIORITY -50
RUNTIMECAP '3 MINUTE'
RUNTIMEPRIORITYTHRESHOLD 0;
-- Пул для тяжелых длинных запросов
CREATE RESOURCE POOL slowly
MEMORYSIZE '0%'
MAXMEMORYSIZE '20G'
MAXCONCURRENCY 7
RUNTIMEPRIORITY LOW
QUEUETIMEOUT '15 MINUTE'
RUNTIMEPRIORITYTHRESHOLD 0;
-- Пул для читателей
CREATE RESOURCE POOL readers
MEMORYSIZE '4G'
MAXMEMORYSIZE '10G'
PLANNEDCONCURRENCY 20
MAXCONCURRENCY 10
RUNTIMECAP '5 MINUTE'
PRIORITY 50
RUNTIMEPRIORITYTHRESHOLD 3
CASCADE TO slowly;
General теперь у нас «похудел»:
Что мы сделали:
- Раскидали по группам сессии пищушие, читающие и выполняющие длинные тяжелые запросы.
- Выделили начальную память пулам читателей и писателей, чтобы для большинства коротких запросов память бралась сразу из резервированной для пула без подкачки с General.
- Не стали выделять память пулу тяжелых запросов, все равно его сессии захотят много памяти и резервировать для них, отрезая драгоценную память из General, смысла нет, зато этому пулу разрешили забирать до 20 гб памяти от General в случае необходимости.
- Выставили для пула тяжелых запросов пониженный приоритет выполнения LOW.
- Для пула писателей и читателей выставили приоритет доступа к ресурсам так, чтобы по приоритету выполнения MEDIUM пул писателей был аутсайдером (-50 приоритет), пул General был посередине (нулевой приоритет) и пул для читателей был выше этих пулов (50 приоритет).
- Рационально выставили значения конкурентности пулам, где одновременно могут выполняться 10 запросов писателей, 10 запросов читателей и 7 тяжелых запросов.
- Для ситуаций, когда пользователь запустил тяжелый запрос в пуле читателей, который длиться более 5 минут, указали перевод каскадом таких запросов на пул тяжелых запросов. Это гарантирует, что пул читателей не просядет при выполнении на нем длинных запросов, которые забьют слоты выполнения конкурентов и замедлят конвеер выполнения из очереди быстрых запросов. Для пула писателей выставили ограничения выполнения запросов не более 3 минут, чтобы неоптимизированные запросы вставки или обновления данных сшибались.
- Для пула тяжелых запросов выставили время ожидания в очереди 15 минут. Если все конкурирующие слоты у пула заняты, то после 15 минут ожидания, стоящие в очереди запросы будут прекращены с ошибкой. Это даст понять пользователям, что сервер не висит, а просто в рамках их пула все занято.
- Для пула читателей выставили время в 3 секунды, в течении которых запрос после запуска имеет наивысший приоритет по ресурсам. Это позволит быстро выполнять короткие запросы, освобождая место в пуле для других запросов
Теперь назначаем пользователям нужные пулы и дело сделано:
ALTER USER user_writer RESOURCE POOL writers;
ALTER USER user_reader RESOURCE POOL readers;
ALTER USER user_analytical RESOURCE POOL slowly RUNTIMECAP '1 HOUR' TEMPSPACECAP '10G';
Здесь мы дополнительно, помимо пула, пользователю «user_analytical» ограничили для запросов время выполнения одним часом и разрешили использовать не более 10 гб пространства в TEMP.
Хочу заметить, что все вышеописанное в статье является действием «куда копать», а не примером «что настроить». Сколько и каких будет ресурсных пулов, с какими характеристиками — это все должны решить Вы сами. Можно начать с малого — создать по примеру подобные 3 пула и дальше смотреть по нагрузкам кластера, постепенно балансируя параметры пулов и выделяя группы пользователей по разным пулам. Главное помнить, что:
- Пул General является общим кладезем памяти для всех пулов и лучше его не использовать напрямую для работы пользовательских сессий
- Чем меньше конкурентов, тем меньше скорость проседания железа в пиковых нагрузках
- Сумма максимально разрешенной памяти всех пулов не должна перекрывать память General
Комментарии (0)
[Перевод] Как конструировать слова (от автора, который ненавидит читать)
Теперь не поймите меня неправильно — я все еще немного читаю. Я одолел книги и блоги, новые каналы и журналы. Но когда авторы становятся многословными, у меня замыливается взгляд. Мне скучно.
Все что я вижу — простыня слов.
В детстве я думал, что мое отвращение к чтению — моя слабость. Это было так, пока спустя годы я не осознал, что эта слабость и помогла мне стать хорошим писателем.
Дело в том, что, в основном, я пишу тексты для приложений и сайтов. Здесь краткость лучше восхитительного стиля, на счету каждый знак. А писать текст для интерфейса во многом напоминает дизайн — дизайн слов для людей, которые ненавидят читать.
Люди не читают ваш интерфейс
Многочисленные исследования показывают, как люди не читают в сети. Это работает и для приложений, и для игр, и для любого экрана, с которым вы взаимодействуете. Большинство просто просматривают страницу, выхватывая слова оттуда и отсюда.
Вы удивитесь, сколько людей нажали «Continue».
Люди ленивы? Небрежны? Или они просто ненавидят читать? Какую бы теорию не предложи, результаты будут все те же. Люди не будут читать твой интерфейс — неважно, насколько потрясающие слова вы подобрали.
Исходя из этого, вы не должны просто писать слова и вставлять их в ваш дизайн. Как только вы напишите слова, возможно, вы поймете, что нужно изменить и его. Если вы не можете объяснить действие в нескольких словах, это сигнал того, что ваша конструкция слишком сложна.
Иначе: вы не должны создавать дизайн с lorem ipsum (условным, бессмысленным текстом-заполнителем).
7 советов по дизайну слов
Будучи автором для интерфейсов, я научился нескольким вещам, которые помогут сделать слово легче для прочтения. Надеюсь, эти советы пригодятся при написании и дизайне ваших собственных слов.
1. Сокращайте
Самая важная вещь, которую вы можете сделать для облегчения читателей — укоротить ваш текст. После написания черновика сократите его, затем снова и снова. Выбрасывайте детали, используйте простые слова и говорите только по делу. Будьте безжалостным.
Чем короче ваш текст — тем выше вероятность, что его прочтут.
Как писатель я прекрасно понимаю, как заманчиво растечься мыслью по древу и расписать свои идеи, но интерфейс не место для этого. Для этого есть Хабр Medium :).
2. Добавляйте заголовки
Иногда текст уже невозможно сократить. Тогда посмотрите, можно ли добавить заголовок, который передает содержание в нескольких словах. Используйте ключевые слова, которые может искать пользователь. Они всегда могут прочесть о том, что конкретно их интересует.
С заголовками проще «сканировать» текст.
3. Делай списки
Во время просмотра страницы наш взгляд обычно двигается вверх-вниз. Поэтому списки, действительно, легче читать, чем параграфы.
Если вы поймали себя за многократным употреблением таких слов как «и» или «также» внутри абзаца, попробуйте переделать текст в формат списка.
Некоторые платформы, Medium, например, перегружены содержанием — в этом нет ничего плохого. Но иногда бывает непросто читать абзац за абзацем.
Мне нравится делать списки.
4. Давайте перерыв
Когда мне нужно написать много, я использую визуальные перебивки, которые позволяют облегчить материал — разрывы строк, картинки, заголовки, примеры — все, что способно разрывать стены из слов. Это дает людям вздохнуть, позволяет подумать и оглядеться, если им это нужно.
К примеру, в моих постах в Medium, я стараюсь писать абзацы из небольшого количества строк и чередовать их с визуальными перебивками.
5. Акцент — на слова
Некоторые авторы слишком много уделяют внимания выбору слов. Подбор слов важен, но, я думаю, форма подачи этих слов важна не меньше.
Когда вы подбираете слова, подумайте о том, как подчеркнуть самые важные слова на экране и как скрыть самое ненужное. В дизайне это называют визуальной иерархией.
Подумайте о жирности шрифта, размере, цвете, контрасте, капитализации, расстоянии, близости, выравнивании, перемещении — все эти вещи имеют большое влияние. При этом неважно, читают люди ваши слова или нет. Настраивайте, меняйте атрибутику до тех пор, пока не найдете нужный баланс.
Что легче прочесть?
6. Не всё сразу
Когда вы пытаетесь объяснить пользователю, как что-то сделать, заманчиво просто поместить всю нужную информацию на одном экране и надеяться на то, что они ее прочтут. Но если ваш текст длиннее нескольких строк, то шанс, что его прочтут многие — минимален. Что тогда делать?
Иногда можно показывать небольшой кусочек информации в определенный период времени. Говоря языком учебника, требуется прогрессивное раскрытие, но я бы назвал его медленным открытием (звучит драматичнее, не так ли?). Попробуйте разбить информацию на части и преподносить ее шаг за шагом.
Много текста? Выдавайте его по частям.
Другая вещь, которой вы можете воспользоваться — убрать подробное описание из текста и сделать детальную информацию ссылкой.
7. Пишите в макетах, а не документах
Вы когда-нибудь писали что-то, что хорошо смотрится на бумаге, но в конечном варианте выходит слишком длинно? Так происходит, когда вы пишете в Google Docs, Dropbox Paper или любом другом из приложений.
Когда вы пишете для интерфейса, ключевым является видеть весь контекст. Вы должны знать как будут выглядеть ваши слова со всем, что их окружает.
Поэтому я предпочитаю писать не в документах, а в Mock-объектах — так я вижу контекст моих слов.
Напутствие
Слова наполняют наш мир смыслами. Они помогают нам понять мир вокруг нас. Правда, печально то, что многие просто не любят читать. Если вы работает со словами так же, как работаю с ними я, наша цель должна заключаться в том, чтобы сделать чтение максимально простым. Помочь людям понять мир вокруг них.
Советы выше это лишь часть того, чем я пользуюсь во время дизайна слов. Придумали свои советы? Пожалуйста, делитесь своими идеями, историями и комментариями ниже.
И для тех, кто ненавидит читать — спасибо, что прочитали.
Перевод: Лиза Ламова
Поддержка публикации — компания Edison, которая разработала электронный сервис передач заключенным и реализовала систему продажи билетов на междугородние маршруты.
Комментарии (0)
[Перевод] Как работает стриминг Netflix
«Если вы можете кэшировать всё очень эффективным способом, то вы часто можете изменить правила игры»
Мы, разработчики программного обеспечения, часто сталкиваемся с проблемами, требующими распространения некоторого набора данных, который не соответствует названию «большие данные». Примерами проблем такого типа являются следующие:
- Метаданные продукта в интернет-магазине
- Метаданные документа в поисковой машине
- Метаданные фильмов и ТВ-шоу
Сталкиваясь с этим, мы обычно выбираем один из двух путей:
- Хранение этих данных в каком-то централизованном хранилище (например, реляционная СУБД, информационный склад NoSQL или кластер memcached) для удалённого доступа пользователей
- Сериализация (например, как json, XML и т.д.) и распространение среди потребителей, которые будут хранить локальную копию
Применение каждого из этих подходов имеет свои проблемы. Централизация данных может позволить вашему набору данных неограниченно расти, однако:
- Имеют место задержки и ограничения по полосе пропускания при взаимодействии с этими данными
- Удалённый информационный склад не может сравниться по надёжности с локальной копией данных
С другой стороны, сериализация и сохранение локальной копии данных полностью в ОЗУ может обеспечить на порядки меньшее время задержки и более высокую частоту доступа, однако и этот подход несёт с собой проблемы, связанные с масштабированием, которые становятся более комплексными по мере увеличения набора данных:
- Объём динамической памяти, занимаемой набором данных, растёт
- Получение набора данных требует загрузки дополнительных битов
- Обновление набора данных может потребовать значительных ресурсов ЦП или влиять на работу автоматического управления памятью
Разработчики часто выбирают гибридный подход — кешируют локально данные с частым доступом и используют удалённо — с редким. Такой подход имеет свои проблемы:
- Управление структурами данных может потребовать значительного количества динамической кэш-памяти
- Объекты часто хранятся довольно долго, чтобы их можно было распространять, и отрицательно влияют на работу автоматического управления памятью
В Netflix мы осознали, что такой гибридный подход часто создаёт лишь иллюзию выигрыша. Размер локального кэша часто является результатом тщательного поиска компромисса между задержкой при дистанционном доступе для многих записей и требованием к хранилищу (хипу) при локальном хранении большего количества данных. Но если вы можете кэшировать всё очень эффективным способом, то вы часто можете изменить игру — и держать весь набор данных в памяти, используя хип меньшего размера и меньше загружая ЦП, чем при хранении лишь части этого набора. И здесь вступает в действие Hollow — последний проект с открытым исходным кодом от Netflix.
Hollow представляет собой Java-библиотеку и всеобъемлющий набор инструментов для использования расположенных в оперативной памяти наборов данных малого и среднего размера, которые распространяются от одного производителя ко многим потребителям с доступом только для чтения.
«Hollow изменяет подход… Наборы данных, для которых ранее такую возможность никогда нельзя было даже рассматривать, теперь могут быть кандидатами для Hollow.»
Функционирование
Hollow сосредоточен исключительно на своём предписанном наборе проблем: хранение цельного набора данных «только для чтения» в оперативной памяти потребителей. Он преодолевает последствия обновления и выгрузки данных из частичного кэша.
Благодаря своим рабочим характеристикам Hollow изменяет подход с позиции размеров соответствующих наборов данных для решения при помощи оперативной памяти. Наборы данных, для которых ранее такую возможность никогда нельзя было даже рассматривать, теперь могут быть кандидатами для Hollow. Например, Hollow может быть полностью приемлемым для наборов данных, которые, если представлять их в json или XML, потребовали бы более 100 Гб.
Быстрота адаптации
Hollow не просто улучшает функционирование — этот пакет значительно усиливает быстроту адаптации команды при работе с задачами, связанными с наборами данных.
Использование Hollow является простым прямо с первого шага. Hollow автоматически создаёт пользовательский API, базирующийся на специфической модели данных, благодаря чему пользователи могут интуитивно взаимодействовать с данными, пользуясь преимуществами выполнения IDE-кода.
Но серьёзный выигрыш возникает при использовании Hollow на постоянной основе. Если ваши данные постоянно находятся в Hollow, то появляется много возможностей. Представьте, что вы можете быстро пройти весь производственный набор данных — текущий или из любой точки в недавнем прошлом, вплоть до локальной рабочей станции разработки: загрузить его, а затем точно воспроизвести определённые производственные сценарии.
Выбор Hollow даст вам преимущество на инструментарии; Hollow поставляется с множеством готовых утилит, чтобы обеспечить понимание ваших наборов данных и обращение с ними.
Устойчивость
Сколько девяток надёжности вы хотели бы иметь? Три, четыре, пять? Девять? Будучи локальным хранилищем данных в оперативной памяти, Hollow не подвержен проблемам, связанным с окружающей средой, в том числе с сетевыми сбоями, неисправностями дисков, помехам от соседей в централизованном хранилище данных и т.д. Если ваш производитель данных выходит из строя или ваш потребитель не может подключиться к хранилищу данных, то вы можете работать с устаревшими данными — но данные будут по-прежнему присутствовать, а ваш сервис будет по-прежнему работать.
Hollow был доработан в течение более чем двух лет непрерывной жёсткой эксплуатации на Netflix. Мы используем его для предоставления важных наборов данных, необходимых для выполнения взаимодействия в Netflix, на серверах, быстро обслуживающих в реальном времени запросы клиентов при максимальной производительности или близко к ней. Несмотря на то, что Hollow затрачивает громадные усилия, чтобы выжать каждый последний бит производительности из аппаратных средств серверов, огромное внимание к деталям стало частью укрепления этой критической части нашей инфраструктуры.
Источник
Три года назад мы анонсировали Zeno — наше действующее в настоящее время решение в этой области. Hollow заменяет Zeno, но является во многом его духовным преемником.
Концепции Zeno в отношении производителя, потребителей, состояния данных, копий состояния объекта и изменений состояния перешли в Hollow
Как и прежде, временная последовательность изменяющегося набора данных может быть разбита на дискретные состояния данных, каждое из которых представляет собой полную копию состояния данных на определённый момент времени. Hollow автоматически определяет изменение состояний — усилие, требуемое от пользователя на поддержание обновлённого состояния, является минимальным. Hollow автоматически дедуплицирует данные, чтобы минимизировать объём динамической памяти наших наборов данных у потребителей.
Развитие
Hollow берёт эти концепции и развивает их, улучшая почти каждый аспект решения.
Hollow избегает использовать POJOs как представление в оперативной памяти — взамен заменяет их компактным, с фиксированной длиной, сильно типизированным шифрованием данных. Такое шифрование предназначено как для минимизации объёма динамической памяти наборов данных, так и для снижения доли стоимости, связанной с ЦП, при обеспечении доступа к данным в реальном времени. Все зашифрованные записи упакованы в повторно используемые блоки памяти, которые располагаются в JVM-хипе, чтобы предотвратить воздействие на работу автоматического управления памятью на работающих серверах.
Пример расположения в памяти записей типа OBJECT
Наборы данных в Hollow являются самодостаточными — для сериализированного блоба, чтобы этот блоб мог бы быть использован фреймворком, не требуется сопровождение из кода, специфического для варианта использования. Дополнительно Hollow разработан с обратной совместимостью, благодаря чему развёртывание может происходить реже.
«Возможность построения мощных систем доступа, независимо от того, предполагались ли они изначально при разработке модели данных.»
Поскольку Hollow полностью построен на оперативной памяти, то инструментарий может быть реализован при условии, что произвольный доступ по всей ширине набора данных может быть выполнен, не выходя из Java-хипа. Множество готовых инструментов входит в состав Hollow, а создание ваших собственных инструментов благодаря базовым компоновочным блокам, предоставляемым библиотекой, является несложным делом.
Основой использования Hollow является концепция индексирования данных различными способами. Это обеспечивает O(1)-доступ к соответствующим записям в данных, что даёт возможность построения мощных систем доступа независимо от того, предполагались ли они изначально при разработке модели данных.
Преимущества
Инструментарий Hollow легко установить и он имеет интуитивно понятное управление. Вы сможете понять в ваших данных некоторые аспекты, о которых вы и не подозревали.
Инструмент отслеживания изменений позволяет проследить изменение определённых записей во времени
Hollow может усилить ваши возможности. Если что-то в какой-то записи кажется неправильным, то можно точно выяснить, что и когда случилось, используя простой запрос в инструмент отслеживания изменений. Если происходит авария и случайно происходит выпуск ненадлежащего набора данных, то ваш набор данных можно откатить назад к тому, который был перед возникновением ошибки, зафиксировав производственные проблемы на их путях. Поскольку переход между состояниями происходит быстро, то это действие может дать результат на всём парке машин уже через несколько секунд.
«Если ваши данные постоянно находятся в Hollow, то появляется много возможностей.»
Hollow проявил себя как чрезвычайно полезное средство на Netflix — мы увидели повсеместное уменьшение времени запуска серверов и снижение занимаемого объёма динамической памяти при постоянно возрастающей потребности в метаданных. Благодаря целенаправленным усилиям по моделированию данных, осуществляемым по результатам детального анализа использования динамической памяти, который стал возможным с появлением Hollow, мы сможем и дальше улучшать показатели.
В дополнение к выигрышу в качестве функционирования мы видим огромный прирост производительности, связанный с распространением наших каталожных данных. Это объясняется отчасти тем инструментарием, который имеется в Hollow, а отчасти той архитектурой, которая была бы невозможна без него.
Заключение
Везде, где мы видим проблему, мы видим, что она может быть решена при помощи Hollow. Сегодня Hollow доступен для использования всему миру.
Hollow не предназначен для работы с наборами данных любого размера. Если данных достаточно много, то сохранение всего набора данных в памяти не представляется возможным. Однако при использовании надлежащей структуры и некоторого моделирования данных этот порог может быть намного выше, чем вы думаете.
Документация имеется на http://hollow.how, а код — на GitHub. Мы рекомендуем обратиться к краткому руководству — потребуется лишь несколько минут, чтобы просмотреть деморолик и увидеть работу, а ознакомление с полностью промышленной реализацией Hollow требует примерно час. После этого можно подключить вашу модель данных и — вперёд.
Если вы начали работать, то можно получить помощь непосредственно от нас или от других пользователей через Gitter или Stack Overflow, поместив метку «hollow».
Комментарии (0)
[Перевод] Доступность VR для людей с ограниченными возможностями
Некоторые из таких барьеров VR неустранимы. Есть люди, которые просто никогда не смогут принять участие в той VR, которая существует сейчас. Это люди, которые не смогут справиться с симуляционным укачиванием, люди, которые просто физически не могут надеть громоздкое устройство на голову.
Но другие барьеры можно обойти благодаря правильным дизайнерским решениям и концепции доступности.
Мы пока находимся в начале нынешнего поколения VR, поэтому пост не будет ответом на все вопросы или набором конкретных инструкций. Существуют не рассмотренные здесь проблемы, в которых есть много пространства для инноваций, открытия нового и создания лучших паттернов дизайна.
Однако статья может ответить на некоторые вопросы, указать на специфичные для VR барьеры доступности, показать возможные решения, позволяющие в результате охватить виртуальной реальностью больше людей.
Симуляционное укачивание
"Из-за «морской болезни» я перестал покупать игры, в которых используется искусственное движение. Я пробовал играть в них в течение 6 недель и каждый раз чувствовал тошноту".Симуляционное укачивание возникает из-за того, что часть чувств сообщает мозгу, что происходит одно, в то время как другие чувства сообщают о другом – возникает сенсорное несоответствие между восприятием зрительной системы и вестибулярного аппарата. Это очень похоже на «морскую болезнь», только наоборот. «Морская болезнь» возникает, когда зрительная система сообщает, что вы неподвижны, но вестибулярный аппарат говорит, что вы двигаетесь. Симуляционное укачивание возникает, когда зрительная система говорит, что вы движетесь, а вестибулярный аппарат сообщает о неподвижности.
Lord Wibbley из Reddit
Решение проблемы симуляционного укачивания — это область обеспечения доступности, в которую вкладывается больше всего усилий. Это неудивительно, учитывая её роль в непопулярности VR-индустрии в начале 90-х.
«Домашняя версия Sega VR так и не была выпущена, потому что у многих пользователей возникала „морская болезнь“». Том Калинске рассказывал в интервью Hyper: «У нас были огромные надежды на неё в девяностых, но технология ещё была не готова. Кроме того, почти каждого укачивало от погружения в VR».Эта важная и превалирующая проблема. Некоторые люди никогда не смогут из-за неё играть в VR, вне зависимости от качества оборудования и ПО. Для некоторых людей даже надевания очков и осматривания по сторонам достаточно получения симуляционного укачивания.
Sega & VR – Ahead Of It’s Time
Некоторые — но не все — люди могут адаптироваться благодаря акклиматизации. Однако я скептически отношусь к степени её возможности. Всегда есть люди, которые просто не будут пробовать во второй раз, если первый опыт был неудачным. Шанс того, что второй раз будет не таким ужасным, не выглядит достаточно веской причиной.
У меня самого был ужасный опыт. Я находился в ситуации, когда должен проверить доступность VR-игры, и у меня была на это одна попытка. После появления ощущения приступа я заставлял себя терпеть его ещё четверть часа, чтобы полностью проверить игру.
Никогда этого не делайте!
В результате я проболел следующие два дня и ощущал негативные эффекты ещё около года. В течение прошлого года я регулярно страдал от укачивания в машине, чего со мной не было с детства. Сейчас быстрое перемещение в фильма и игра в FPS тоже вызывают сложности, которых я раньше не испытывал.
Я читал другие отчёты о тех же долговременных эффектах неудачного опыта. Хотя это очевидно нечастые и экстремальные случаи. Но вам точно не нужен опыт, который настолько плох, что подкосит вас.
И, разумеется, это не только важно с точки зрения опыта отдельных игроков. Это важно для всей индустрии VR с точки зрения рекламы. Хорошо известный пример негативного случая на показе Resident Evil на E3 отвлекает внимание от множества положительных историй.
Многие люди могут избежать симуляционного укачивания в случае использования правильных дизайнерских решений. Цель заключается в том, чтобы глаза не передавали ощущение движения, когда внутреннее ухо и другие органы говорят об отсутствии движения.
Вот некоторые из существующих техник:
- Опции перемещения, позволяющие избегать ощущений движения, несоответствующих движениям игрока.
- Постоянный контроль игрока над камерой и постоянное управление ею движениями головы по умолчанию (хотя дополнительная опция использования контроллера и полезна для людей с проблемами с моторикой.)
- Динамическое уменьшение периферийной видимости при движении.
- Предоставление игроку опорной точки для взгляда (например, тропы или кокпита).
- Сохранение постоянного уровня горизонта.
- Избегание быстрого движения объектов к игроку, от игрока и рядом с ним (в том числе больших объектов, двигающихся близко к голове игрока).
- Отсутствие ускорения и замедления
- Сохранение стабильно высокого уровня кадров в секунду (минимальные требования сейчас зависят от платформы и результатов исследований – 60 fps, 75 fps, 90 fps – но они всегда должны оставаться постоянными) и низкой латентности (ниже 20 мс)
- Избегание любого типа эффекта смазывания (в особенности в области периферийного зрения)
- Отсутствие быстрого перемещения головы (для снижения риска сдвига оборудования при использовании).
- Грамотное использование терминов, например «удобство» вместо «неприятных ощущений», потому что сама мысль о симуляционном укачивании может сделать игрока более чувствительным к нему.
Есть множество других решений и литературы по этому вопросу. Поэтому, чтобы не повторяться, перечислю несколько хороших источников:
- Best Practices: Simulation Sickness, Oculus
- Simulation Sickness and VR — What is it, and what can developers and players do to reduce it? by Ben Lewis-Evans
- How to Avoid the Effect of Motion Sickness in VR, VRScout
- VR and Simulation Sickness, by Unreal
- Do the locomotion: How VR devs are expanding the virtual space, by Kris Graft
- This is Your Brain on VR, Kimberly Voll
Некоторые решения проблемы симуляционного укачивания могут быть реализованы как неотъемлемая часть опыта игры, другие реализуются через опции. Эти опции с самого начала виделись как некий «комфортный режим». Например, в The Gallery: Six Elements комфортный режим заменял свободное аналоговое движение поворота на переключение с шагом в 30 градусов.
«В VR всё решают опции, а комфортный режим VR (Comfort Mode) — дополнительный режим новичка, который оказался очень удобным на практике. Не всем он понравится, но он меньше разрушает эффект погружения, чем приём средств от укачивания. Наша цель — дать людям широкие возможности, чтобы они оставались в симуляции как можно дольше».Но всё равно следует учитывать, что в игру будет играть множество людей, не знающих, что им требуется комфортный режим. Так что лучше включить его по умолчанию, и позволить освоившимся игрокам переключаться на режим, более подверженный укачиванию, но и с большим погружением".CloudHeadGames на Reddit
«Когда я закончил, у меня было чувство тошноты. Мне нужно было присесть и немного отдохнуть. Но я думаю, что это было из-за первых пяти минут, а не последних пятнадцати. Если бы комфортные настройки были включены с самого начала, думаю, ощущения были бы нормальными».Симуляционное укачивание было большой проблемой игр уже давно, ещё до VR. В частности, в играх от первого и третьего лица. Такие аспекты, как изначально хорошая и настраиваемая область видимости, а также переключение режимов размытия и перемещения оружия, значительно влияют на восприятие.Dan Crawley на venturebeat.com
«Игры с двумя типами одновременного движения, например, покачиванием головы (при ходьбе голова немного двигается вверх-вниз) и перемещением оружия (при ходьбе оружие двигается вверх-вниз), каждый раз вызывают у меня тошноту».Несмотря на свою важность и отрицательное влияние на игры, немногие разработчики осознают этот фактор. Я надеюсь, что разработчики игр усвоят уроки VR о зрительном и вестибулярном несоответствии и применят их не только в VR. Если VR сможет привлечь внимание к проблеме во всей индустрии, то это будет замечательно и сделает игры гораздо более приятными для большего количества людей.
Eric Qualls на about.com
Двигательная недостаточность
«Как игрока с ограниченными возможностями меня волнует вопрос VR. Я не могу ходить, и даже с трудом двигаю руками. Не останутся ли люди вроде меня за бортом с развитием технологий виртуальной реальности?»Двигательная доступность в видеоиграх традиционно означает способность управлять контроллером. Если не учитывать малое количество игр с управлением жестами, это означает, что требования игр к моторике сосредоточены на руках и кистях.Johanna Roberts на YouTube
В VR диапазон и сложность требований к моторике значительно повышены. В особенности из-за громоздкого головного оборудования текущего поколения. Уже есть многообещающие аппаратные разработки, например, VR с управлением взглядом, но они пока недоступны на массовом коммерческом рынке.
Ограничения моторики в VR включают в себя:
Силу/уставаемость – способность/количество времени возможного выдерживания веса на голове или в руках, а также выполнения повторяющихся действий.
Диапазон движений – насколько голова или руки могут перемещаться в любом направлении, насколько хорошо двигаются пальцы, в особенности в случае контроллеров с кнопками на разных сторонах, а также органов управления, расположенных на самом головном оборудовании.
Точность – способность выполнять небольшие, плавные или точные движения
Рост – в широком диапазоне, включая сидение на кресле-коляске.
Двигательную активность – способность ходить, наклоняться, приседать или вставать на колени
Наличие частей тела и пальцев – не у каждого человека с двумя руками есть десять действующих пальцев.
Скорость – способность выполнения задания в течение заданного промежутка времени.
Равновесие и проблемы с равновесием – в особенности у пожилых игроков.
Всё перечисленное — это очевидные проблемы. Некоторые барьеры, поставленные VR для моторики, непреодолимы, но большинство можно обойти. Существуют и очевидные, и довольно интересные решения. Можно предоставить игрокам выбор способов ввода, настраиваемую высоту головы, опции навигации по окружению и диапазону движений. Если концепция игры не может избавиться от таких зависимостей, то это нормально. Игры по определению должны содержать в себе барьеры, а любые барьеры ограничивают. Можно проанализировать барьеры в механике игры, выяснить, какие из них необходимы, а какие нет, и оптимизировать игровой опыт, чтобы он доставлял удовольствие как можно большему количеству людей.
Многие люди уже проделали отличную работу в этой области, и это на текущем этапе развития индустрии воодушевляет:
Повторюсь, хотя перечисленные выше подходы и удивительны, это всего лишь первые шаги. Здесь есть большое поле для инноваций и нахождения новых способов избавления от необязательных ограничений.
Как и в случае игр без VR, ключевой момент — наличие опций. Например, опция использования стандартного контроллера вместо отслеживания движений руки или ходьбы. Она полезна не только для людей с недостаточными для игры в Vive точностью и диапазоном движений. Она полезна также и для людей, более подверженных травмам, риск которых может повышаться, когда игрок не видит угла и положения своих конечностей. Поставляемый с PSVR набор игр — прекрасный пример возможности выбора между управлением движением и стандартными контроллерами.
Выбор между стандартными контроллерами и управлением движением.
Очень важно понять, что оптимальный с вашей точки зрения способ погружения в игру — не единственный. Если кто-то сможет ощутить 80% вашего видения игры, то это намного лучше, если он ощутит 0%.
Допустим вы видите игру как «комнатную» VR с перемещением головы на 360 градусов и полным отслеживанием движений рук. Но игрок, не имеющий возможности поворачивать голову в горизонтальной плоскости или не имеющий двигательной способности вообще, всё равно может получить больше ощущений от игры, чем кто-нибудь другой.
Утеря слуха
Звук — важная часть VR-опыта, имеющая, однако, жёстко заданный формат. Даже в случае высококачественного 3D/бинаурального звука механизмом «доставки» всегда служат только стереонаушники. Широко распространённая односторонняя тугоухость (неравномерная утеря слуха правого и левого уха) ограничивает восприятие жёстко разделённого стереозвука.
«С рождения я наполовину глух. У меня работает только правое ухо. Меня это никогда не ограничивало, потому что я не знал ничего другого. Но это относится только к реальному миру. Что касается игр, а теперь и виртуальной реальности, то мне очень мешает стереозвук».Включение моно-режима (проигрывание обоих стереоканалов через оба уха) — очень ценная функция в играх без VR. Но она означает, что вы теряете и ощущение направления.khannr2 на reddit
В реальной жизни односторонняя тугоухость частично компенсируются эхом. Например, глухой на левое ухо человек может немного слышать звуки слева, потому что они отражаются от поверхностей справа. Это может быть интересной областью исследования, в особенности для игровых движков. Уже есть интересные работы по более точному представлению звука (самая последняя — в Gears of War 4), но тут ещё много возможностей для инноваций.
Но одной из самых серьёзных проблем при утере слуха в VR сейчас являются субтитры (текстовый аналог речи/других важных звуков). Точнее, их отсутствие.
«Когда я играл в демо Robot Repair компании Valve, я должен был выполнять инструкции, которых не слышал. Я осознал, что возможно, в VR-играх может вообще не быть субтитров, и это не позволит мне насладиться множеством возможностей, которые я хочу испытать».Функция, ставшая почти стандартом для всех игровой индустрии, отсутствует во множестве VR-игр. Естественно, она влияет на возможность доступности для людей со слабым слухом и на затраты на локализацию. Важный урок здесь в том, что если не учитывать доступность игр для людей с ограниченными возможностями, то ситуация очень легко может становиться ещё хуже.Karmagon на Reddit
Почему же так происходит?
Похоже, что есть довольно простой ответ. Субтитры в других медиа не представляют большой проблемы для дизайна и расположены в нижней части экрана. Но в VR нет нижней части экрана. Поэтому это представляет проблему для дизайна.
Можно расположить их в нижней части области видимости игрока. Для этого они должны быть прямо рядом с игроком, чтобы их не перекрывали окружающие объекты.
Субтитры, плавающие перед игроком в The Vanishing of Ethan Carter
Однако здесь есть проблема: конфликт сигналов вергенции и приспособляемости, подробно описанный здесь Эдриен Хантер Adrienne Hunter.
Итак, вариант с плавающими субтитрами неприменим из-за напряжения глаз, головных болей и тошноты. Что остаётся ещё? Другой подход — делать субтитры контекстными, привязывать их к источникам звука, которыми чаще всего бывают персонажи игры.
Здесь конфликт сигналов вергенции и приспособляемости не возникает. Но тогда появляется другая проблема. Что если игрок смотрит в другом направлении? Если у вас нет возможности узнать, что кто-то говорит, то нет причин оглядываться и читать текст. В результате получается система гораздо хуже, чем используемые вне VR, поэтому это тоже неидеальное решение.
И, как часто бывает, если нет очевидного дизайнерского решения, то его просто игнорируют.
Но эту проблему можно решить. У неё есть такие решения, как ранний прототип VR-субтитров разработчика из Мельбурна Джо Уинтергрина (Joe Wintergreen). Прототип сочетает в себе два подхода: контекстное расположение текста при нахождении в области видимости игрока и прикрепление его к фиксированной точке, если источник невидим для игрока. Это позволяет игроку выбирать, хочет ли он повернуться к источнику.
Пример реализации: http://ift.tt/2fEN6Ic
Как и в случае ограничений моторики, это только первый шаг, здесь есть большие возможности для инноваций. Например, можно улучшить систему, добавляя имя говорящего, если присутствуют несколько источников звука, или указывая на местоположение источника звука (размещая текст слева/справа или с помощью стрелок). Также пригодятся рекомендации по дизайну субтитров — в особенности следует уделить внимание размеру и контрастности.
Но это самый многообещающий подход, из тех, что видел лично я. Он позволяет избежать конфликта сигналов вергенции и приспособляемости и делает текст доступным, даже если говорящий не виден.
И, разумеется, речь — это не все звуки. Это относится и к играм без VR, но особенно важно в виртуальной реальности из-за жёсткого разделения аудиосигналов: не стоит полагаться на звук для передачи важной информации. Используйте несколько каналов, т.е. передавайте информацию и визуально. Это не только делает информацию доступной людям с утерей слуха, но и часто является хорошим дизайнерским решением для всех игроков — усиливает передачу и ускоряет распознавание информации.
Светочувствительная эпилепсия
«Не думаю, что испытывала что-то более ужасающее, чем мой первый приступ. Такого не пожелаешь и худшему врагу».Проблема светочувствительной эпилепсии — редко встречающаяся, но критически важная область обеспечения доступности. Несмотря на то, что она возникает в малом количестве случаев эпилепсии, последствия её очень серьёзны. Обычно доступность подразумевает избавление от плохих ощущений или от невозможности поиграть в игру. Или, как в случае симуляционного укачивания, от довольно сильного дискомфорта. Но эпилепсия приводит к реальному физическому ущербу.Cathy Vice, IndieGamerChick.com
Поэтому производители как можно убедительнее уговаривают людей с эпилепсией не использовать VR-оборудование. Но вот в чём проблема — единственный способ обнаружить у себя эпилепсию — испытать её приступ. Обязательная домашняя проверка на эпилепсию компании Ubisoft была введена в результате первого приступа ребёнка, игравшего в Rabbid Rabbits.
Важно заметить, что игры не «заражают» игроков эпилепсией, но они могут стимулировать приступы. В том числе у людей с предрасположенностью к ней, но не имевших приступов раньше, и не знающих, что у них есть предрасположенность. Например, по оценкам британской благотворительной организации помощи людям с эпилепсией каждый год в одной только Великобритании около 150 человек испытывают первый приступ, играя в игры.
Исследований по влиянию VR на приступы эпилепсии пока нет. Но фактором воздействия является область видимости, подверженная визуальному эффекту. При просмотре телевизора есть жёсткое ограничение этой области, потому что экран занимает относительно малую часть области видимости. Но в VR эта область, в которой вероятно появление опасных вспышек, мерцаний и цветовых шаблонов, может составлять до 100%.
При полном тонико-клоническом приступе (потеря сознания с последующими спазмами мышц) надетое на голову громоздкое оборудование, прикреплённое к глазам, и кабель, обвивающийся вокруг шеи — не самое лучшее сочетание.
Хотя и невозможно обеспечить полную безопасность игры для людей с эпилепсией, существует стандартный набор общих триггеров, который нужно учитывать для снижения вероятности приступов. Он соотносится с двумя аспектами миганием/мерцанием и повторяющимися высококонтрастными цветовыми шаблонами. Некоторые компании просто не допускают их присутствия в своих играх, другие используют опции для их отключения. Для некоторых триггеров есть пороги, основанные на длительности воздействия и площади, занимаемой на экране.
Но поскольку качественные исследования пока отсутствуют, из-за потенциально более высокого риска и серьёзного ущерба разумнее учитывать «пессимистичный» сценарий и временно отбросить мысль об опциях. Вместо них лучше просто вообще избегать стандартных триггеров, вне зависимости от времени воздействия и площади на экране.
У Oculus есть на этот счёт очень чёткая позиция –
«Вы несёте ответственность за отсутствие намеренного мерцания в играх. …Вы должны убедиться, что контент соответствует стандартам и рекомендациям по безопасности графики».
Нарушения зрения
«Главная страница Oculus выглядит довольно хорошо, но для меня она почти бесполезна. Плитки основной области и маленькие панели слева и справа преднамеренно расположены на виртуальном расстоянии от пользователя. Нет никакой возможности подойти к ним или увеличить их. Я вижу, что плитки там есть, но не могу ничего прочитать. Я знаю из видео на YouTube, что правая панель — это список друзей, а левая — список недавно запущенных игр, или что-то вроде того, но я не могу прочитать информацию на них. К счастью, я могу запускать игры Rift из приложения Oculus во вкладке Library. Если бы я не мог, всё было бы совсем печально».Мелкий текст и размер UI часто становятся причинами жалоб во всех играх, которые едва соблюдают минимальные требования в 28 пикселей при 1080p для стопроцентного зрения, не говоря уж о любой степени нарушений зрения. У игроков часто остаётся единственное решение — сесть поближе к экрану.Jesse Anderson
В VR сесть поближе, разумеется, невозможно, как и играть с постоянно включенным увеличением — в противном случае сильно повышается риск симуляционного укачивания. Это приводит к двум основным выводам:
- Уделяйте большое внимание размеру и контрастности UI и важных элементов геймплея. Предоставьте возможность изменения размера текста.
- Создайте в VR аналог приближения к элементам UI, а не размещайте их на фиксированном расстоянии от пользователя. Слишком большой наклон головы может вызвать проблемы с расстоянием до датчика, но её можно обойти с помощью опции калибровки области видимости.
Приближение к меню в Crystal Rift
Такие решения могут быть полезными и для людей, которые видят хорошо в очках, но оборудование не даёт им возможности использовать их. Это очень частая проблема, тоже уникальная только для VR. Размер мелкого текста особенно часто становится барьером для доступности в играх вообще. Не говоря уже о VR, где игрок не может надеть свои очки.
Также могут быть полезными перекрестия прицела или включающая их опция. Перекрестия могут стать «опорой», предотвращающей симуляционное укачивание. Они также полезны для людей с разным уровнем зрения левого и правого глаза, взгляд которых в VR смещён относительно центра. И, разумеется, как и всегда, для людей с ослабленным зрением полезно изменение опций размера и внешнего вида прицела.
Наконец, коснёмся полной слепоты. Слепота и VR могут казаться несовместимыми, если полагать, что VR — это визуальный носитель информации. Но на самом деле существуют VR-игры, основанные только на звуке, и обычные игры для слепых тоже есть. Существуют даже крупные сообщества слепых игроков в Grand Theft Auto V и Resident Evil 6. Они возможны благодаря сочетанию игровой помощи (например, можно забраться в машину, нажав кнопку неподалёку от неё; есть автоматическое прицеливание, позволяющее поворачиваться в направлении звука и стрелять), превосходного детального звукового дизайна и простого окружения.
Прорывом в GTAV стал режим игры от первого лица. Эта функция кажется тривиальной, но она позволила полагаться только на расположение источников звука. В VR благодаря сочетанию полного контроля за движением головы и качественного 3D-звука эта способность значительно усиливается. В особенности потому, что VR-окружения имеют прямолинейную навигацию, комфортные режимы и перемещение телепортацией. В VR есть даже отслеживание движений рук, позволяющее указывать непосредственно на источник звука, а не перемещать курсор, который игрок не может видеть.
Существуют довольно серьёзные ограничения: во-первых, сложность окружения, во-вторых, взаимодействие с UI. Но о них стоит поразмышлять и пообщаться со слепыми игроками (поищите в Twitter «blind gamer», и найдёте их [прим. пер.: честно говоря, не нашёл ни одного]) о возможных вариантах решения проблемы. Воспользовавшись правильной механикой, вы удивитесь, как много можно сделать, вложив небольшие усилия.
И последнее, о чём не стоит забывать в отношении зрения — уникальную для VR (и AR) проблему – стереослепоту. Чаще всего невозможность увидеть стереокартинку не становится проблемой, особенно если вы учитываете точку над прицелами. Но её всё равно не стоит забывать, если в игре есть моменты, в которых требуется восприятие различий в глубине. Очевидная причина невозможности увидеть стереокартинку — это сниженное зрение или его отсутствие для одного глаза. Поэтому всегда следует отображать такие элементы, как субтитры, на обоих экранах.
Существует ещё один очень интересный аспект стереослепоты: если человек стереоскопически слеп в реальной жизни, это не означает обязательной стереослепоты в VR, как например в этой истории или в этой, с очень интересными последствиями.
Что это всё означает?
Как я упомянул в начале, в статье не приведён исчерпывающий список всех барьеров или всех решений. И, разумеется, существуют другие рекомендации по общедоступности игр для разработчиков, многие из которых применимы и к VR. Но я надеюсь, что сказанное выше заставит хоть кого-нибудь задуматься. И если решение возникнет в эпоху зарождения технологии, в которой мы сейчас находимся, то ему будет проще стать распространённой дизайнерской практикой.
Важно помнить, что даже если некоторые из перечисленных выше барьеров присутствуют в вашей игре, то ничего фундаментально плохого в её дизайне нет. Вы всё равно делаете продукт, который понравится людям. Вопрос только в его доступности, в увеличении количества людей, способных получить от него удовольствие, и в осознании того, какие формы может принять такое удовольствие.
Я ещё не встречал ни кого из индустрии VR, кто был бы достаточно пассионарным евангелистом этого формата и желал бы поделиться своим энтузиазмом с другими, привлечь больше людей. Так как многие создаваемые сейчас игры становятся для игроков первым опытом в VR, то если мы начнём решать проблемы сейчас, гораздо большая часть этих опытов оправдает надежды пользователей.
Комментарии (0)