Способы управления изменением данных дизайнера наряду с изменением данных игрока

14

У меня есть онлайн-игра, в которой игроки каким-то образом формируют мир, например. Жилье Ultima Online, где вы можете строить свои дома непосредственно на определенных участках карты мира. Это изменения, которые должны сохраниться со временем как часть постоянного мира.

В то же время команда разработчиков добавляет новый контент и вносит поправки в старый контент, чтобы улучшить и расширить игру для новых игроков. Они будут делать это на сервере разработки сначала во время тестирования, а затем должны объединить свою работу с «работой» игроков на живом сервере.

Предполагая, что мы исправляем проблемы с дизайном игры - например. игроки могут строить только в определенных областях, поэтому они никогда не конфликтуют географически с изменениями дизайнера - каковы хорошие способы обработки данных или организации структур данных, чтобы избежать конфликтов, когда новые данные дизайнера объединяются с данными нового игрока?

Пример 1: игрок создает предмет нового типа, и игра назначает ему идентификатор 123456. Все экземпляры этого элемента относятся к 123456. Теперь представьте, что разработчики игр имеют похожую систему, и дизайнер создает новый элемент, также пронумерованный 123456. Как этого можно избежать?

Пример 2: кто-то делает популярный мод, который дает всем вашим драконам французский акцент. Он включает в себя скрипт с новым объектом под названием, assignFrenchAccentкоторый они используют для назначения новых голосовых ресурсов каждому объекту дракона. Но вы собираетесь развернуть свой DLC «Наполеон против Смауга», у которого есть одноименный объект - как вы можете сделать это без особых проблем с обслуживанием клиентов?

Я подумал о следующих стратегиях:

  • Вы можете использовать 2 отдельных файла / каталога / базы данных, но тогда ваши операции чтения значительно усложняются. «Показать все элементы» должен выполнить одно чтение в БД дизайнера и одно чтение в БД плеера (и все равно должен как-то различать 2).
  • Вы можете использовать 2 разных пространства имен в одном магазине, например. использование строк в качестве первичного ключа и добавление к ним префикса «DESIGN:» или «PLAYER:», но создание этих пространств имен может быть нетривиальным, а зависимости неясными. (Например. В СУБД вы не сможете эффективно использовать строки в качестве первичных ключей. Вы можете использовать целые числа и распределить все первичные ключи ниже определенного числа, например, 1 миллион, для данных конструктора, а все, что выше этой точки, будет данные игрока. Но эта информация невидима для СУБД, и ссылки на внешние ключи будут пересекать «разрыв», что означает, что все инструменты и сценарии должны явно обходить ее.)
  • Вы всегда можете работать с одной и той же общей базой данных в режиме реального времени, но производительность может быть низкой и риск повреждения данных игрока может быть повышен. Это также не распространяется на игры, которые работают на более чем 1 сервере с различными мировыми данными.
  • ... есть другие идеи?

Мне приходит в голову, что, хотя это в первую очередь проблема для онлайн-игр, концепции могут применяться и к моддингу, когда сообщество создает моды в то же самое время, когда разработчики исправляют свою игру. Используются ли здесь какие-либо стратегии, чтобы уменьшить вероятность взлома мода при выходе новых патчей?

Я также пометил это как «контроль версий», потому что на одном уровне это то, что это - две ветви разработки данных, которые необходимо объединить. Возможно, некоторые идеи могут прийти с этого направления.

РЕДАКТИРОВАТЬ - некоторые примеры, добавленные выше, чтобы помочь прояснить проблему. Я начинаю думать, что проблема в действительности связана с пространством имен, которое может быть реализовано в магазине с помощью составных ключей. Это упрощает стратегию слияния, по крайней мере. Но могут быть альтернативы, которых я не вижу.

Kylotan
источник
1
Я полагаю, что ответ на этот вопрос может зависеть, по крайней мере частично, от того, какой тип данных добавляют дизайнеры и что добавляют игроки.
lathomas64
Возможно, но меня больше интересуют общие решения для двух сторон, которые вносят свой вклад в единое хранилище данных.
Kylotan
1
Многие люди упускают суть этого вопроса - противоречивы не изменения игроков: скорее обновления контента и т. Д., Нарушающие существующие макеты. @ Килотан, я прав?
Джонатан Дикинсон
Именно здесь обновления контента для разработчиков могут конфликтовать с обновлениями контента для игроков. На самом деле меня не интересуют обходные пути в игровом дизайне (например, позволяют игрокам строить только в определенных местах), а обходные пути в структуре данных (например, позволяют игрокам создавать вещи с идентификаторами, превышающими 1 миллион).
Kylotan
2
Вы не указали, ожидаете ли вы обновления в реальном времени для живого мира? Примечание: две стороны, вносящие вклад в единое хранилище данных, являются базой данных, это то, что делают базы данных, вы не можете обойти этот факт, и было бы глупо игнорировать десятилетия знаний о том, как избежать проблем с общими данными.
Патрик Хьюз

Ответы:

2

Я думаю, что ответы, предлагающие решения БД, переходят к конкретной реализации без понимания проблемы. Базы данных не облегчают слияния, они просто дают вам основу для хранения ваших данных. Конфликт все еще конфликт, даже если он находится в БД. И проверка - решение проблемы для бедного человека - это будет работать, но с огромными затратами для вашего удобства.

То, что вы здесь говорите, относится к распределенной модели развития проблемы. Я считаю, что первый шаг - не думать об игроках и дизайнерах как об отдельных типах создателей контента. Это устраняет искусственное измерение вашей проблемы, которое не влияет на решение.

По сути, у вас есть основная линия - каноническая версия, утвержденная разработчиком. У вас (возможно) могут быть и другие ветки - живые серверы, на которых люди активно разрабатывают моды и делятся ими. Контент может быть добавлен в любую ветку. Важно отметить, что ваши дизайнеры здесь не являются чем-то особенным - они просто создатели контента, которые живут внутри дома (и вы можете найти их и ударить, когда они облажаются).

Тогда принятие пользовательского контента является стандартной проблемой слияния. Вы должны либо вытянуть их изменения обратно в основную линию, объединить, затем вытолкнуть снова, либо перенести изменения основной линии в их ветвь и объединить (оставив основную линию «чистой» от созданного пользователем материала). Как обычно, тянуть к своей ветке и исправлять это более дружелюбно, чем просить других людей вытащить ваши изменения и затем пытаться исправить это удаленно с их стороны.

Как только вы работаете с моделью такого типа, применяются все обычные процессы предотвращения конфликтов слияния. Некоторые из наиболее очевидных:

  • Поощряйте либеральное использование пространств имен для ограждения контента от конкретного автора / мода / команды.
  • Там, где контент должен взаимодействовать, установите четкие соглашения о вызовах / использовании, соглашения об именах и другие свободные «правила», которые направляют разработку, чтобы ее было легко объединить. Предоставьте инструменты, позволяющие создателям контента знать, соблюдают ли они эти правила, идеально интегрированные в сам процесс создания контента.
  • Предоставить инструменты отчетности / анализа для выявления возможных слияний до их возникновения. Исправление после слияния, вероятно, очень болезненно. Сделайте так, чтобы можно было проверить определенный бит контента и дать ему все ясно как готовый к слиянию, чтобы слияние было безболезненным
  • Сделайте ваши слияния / интеграции надежными. Разрешить легкие откаты. Проведите тщательное тестирование объединенного контента: если он не проходит тестирование, не объединяйте его! Итерируйте либо их содержимое, либо ваше, пока слияние не произойдет чисто.
  • Старайтесь не использовать инкрементные целочисленные идентификаторы (у вас нет надежного способа передать их создателям). Это работает только в БД, потому что сама БД является каноническим поставщиком идентификаторов, поэтому вы никогда не получите дубликаты; однако это также вводит единственную точку отказа / нагрузки в вашей системе.
  • Вместо этого используйте GUID - они стоят дороже для хранения, но зависят от конкретной машины и поэтому не вызовут коллизий. В качестве альтернативы используйте строковые идентификаторы, это намного легче отладить / разрешить, но дороже для хранения и сравнения.
MrCranky
источник
К сожалению, кое-что из этого не помогает моей проблеме (например, когда игроки следуют определенным правилам, поскольку все это должно выполняться автоматически на стороне сервера), и я не думаю, что будет практично поддерживать степень управления слияниями и транзакций семантику, которую вы упоминаете, но общий подход к распределению гарантированных уникальных идентификаторов, возможно, GUID, вероятно, наиболее близок к тому, с чем я пойду.
Kylotan
Ах я вижу. Ну, так как вы контролируете их инструменты построения, по крайней мере, применение этих подходов, удобных для слияния (пространства имен и т. Д.) - это то, что вы можете сделать без согласия игроков.
MrCranky
Что вы делаете, если два игрока создают дублированный контент? Или отдельные экземпляры вашего игрового мира рассматриваются как уникальные? В этом случае, возможно, это полезный подход для автоматической проверки каждого уникального экземпляра, который вам известен, по отношению к вашей основной / основной ветке на наличие конфликтов, которые произойдут, когда вы отправите эти изменения в экземпляры. Если вы не можете контролировать игроков, вы можете, по крайней мере, предупредить свою внутреннюю команду о том, что работа, которую они выполняют, конфликтует с экземпляром X мира, на раннем этапе разработки.
MrCranky
Концепция пространств имен - это не столько проблема, сколько выбор подходящих пространств имен из всех возможных пространств имен! :) И дублирование контента для меня не проблема - это всего лишь 2 экземпляра чего-то, что эквивалентно. Важно то, что не происходит никаких разрушительных слияний или перезаписей. Что касается автоматических проверок столкновений, это останавливает ущерб, нанесенный при записи, но не решает исходную проблему именования. (Переименование вещей, чтобы избежать столкновения, может быть нетривиальным из-за перекрестных ссылок.)
Kylotan
Ах да, теперь я вижу, это не столько пространства имен, сколько выбор имени. В этом случае, вероятно, GUID - это снова ответ - содержание эффективно хранится в своей маленькой области. Можно дать декоративное имя, но игра будет использовать GUID.
MrCranky
1

Храните все как атрибут (или декоратор) - с точками монтирования. Давайте возьмем дом, который игрок спроектировал в качестве примера:

o House: { Type = 105 } // Simple square cottage.
 o Mount point: South Wall:
  o Doodad: Chair { Displacement = 10cm }
   o Mount point: Seat:
    o Doodad: Pot Plant { Displacement = 0cm, Flower = Posies } // Work with me here :)
 o Mount point: North Wall:
  o Doodad: Table { Displacement = 1m }
    o Mount point: Left Edge:
     o Doodad: Food Bowl { Displacement = 20cm, Food = Meatballs}

Таким образом, каждая сущность может иметь одну или несколько точек монтирования - каждая точка монтирования может принимать ноль или более других компонентов. Эти данные будут храниться вместе с версией, в которой они были сохранены, а также с любыми соответствующими свойствами (например, смещением и т. Д. В моем примере). Скорее всего, NoSQL здесь подойдет (Key = Entity ID, Value = Serialized Binary) Данные).

Каждый компонент должен был бы иметь возможность «обновить» старые данные из предыдущей версии (никогда не удалять поля из сериализованных данных - просто «обнулить» их) - это обновление происходит в ту минуту, когда оно загружено (затем оно сразу же сохраняется в доступна последняя версия). Скажем, в нашем доме изменились размеры. Код обновления относительно определит расстояние между северной и южной стенами и пропорционально изменит смещения всех содержащихся объектов. В качестве другого примера у нашей мясной миски может быть удалено поле «Еда», и вместо этого можно получить «Сорт» (мясо) и «Рецепт» (шарики). Сценарий обновления превратит «мясные шарики» в «мясные», «шарики». Каждый компонент должен также знать, что делать с изменениями в точках монтирования - например,

Все это оставляет ровно одну открытую проблему: что произойдет, если два объекта конфликтуют друг с другом (не их контейнер - точки монтирования защищают вас от этого)? После обновления вы должны проверить наличие коллизий и попытаться разрешить их (разводя вещи, как SAT). Если вы не можете понять, как разрешить столкновение, удалите один из объектов и поместите его в тайник - где они могут купить эти удаленные предметы (бесплатно) или продать их (по полной цене); и, очевидно, уведомить игрока, что обновление сломало некоторые из их макета - возможно, с функцией «увеличения», чтобы они могли увидеть проблему.

В конечном итоге вы должны оставить сложные изменения в руках игроков (быстро потерпеть неудачу), так как никакой алгоритм не может объяснить эстетику - вы должны просто иметь возможность дать игроку контекст относительно того, где был элемент (чтобы он мог запомнить, а не просто приземлиться со всеми этими предметами в своем тайнике и не знать, где они были).

Джонатан Дикинсон
источник
Это слишком узко сосредоточено на позиционировании объекта, что не является ключевой проблемой, которую я пытаюсь решить. Это больше о наличии уникальных идентификаторов в параллельных наборах данных и необходимости их объединения без какого-либо риска конфликта. Я добавил 2 примера в свой пост на днях, чтобы попытаться объяснить немного подробнее.
Kylotan
1

Я пытаюсь связать это с чем-то, что я понимаю, поэтому я думаю сейчас о Minecraft. Я представляю живой сервер, где игроки вносят изменения в режиме реального времени, в то время как разработчики работают на тестовом сервере, исправляя / создавая новый контент.

Ваш вопрос почти как 2 уникальных вопроса:

  1. Как обеспечить уникальность идентификаторов объектов
  2. Как сделать так, чтобы пространства имен скриптов не сталкивались

Я бы попробовал решить # 1 через временную систему ссылок. Например, когда кто-то создает новый объект, он может быть помечен как изменчивый или временный. Я полагаю, что весь новый контент, созданный на тестовом сервере, будет помечен как энергозависимый (хотя он также может ссылаться на энергонезависимый контент).

Когда вы будете готовы перенести новый контент на действующий сервер, ваш процесс импорта найдет изменчивые объекты и назначит им идентификаторы объектов живого сервера, которые установлены в камне. Это отличается от прямого импорта / слияния, потому что вы должны иметь возможность ссылаться на существующие энергонезависимые объекты, если вам нужно исправить или обновить их.

Для # 2 кажется, что вам действительно нужен некоторый уровень промежуточной трансмутации скрипта, который может хешировать имя функции в уникальном пространстве имен. т.е.

assignFrenchAccent

становится

_Z11assignFrenchAccent
Ошибка 454
источник
0

Если файлы данных являются текстовыми, а не двоичными, и дизайнеры и проигрыватели модифицируют различные области, вы можете попробовать объединить SVN.

lathomas64
источник
0

Я думаю, что база данных / файловая система, реплицируемая в средах с процедурой «извлечения», была бы лучше

Таким образом, всякий раз, когда дизайнер хочет внести какие-либо изменения в мир, он извлекает / блокирует все активы, которые он хочет создать / изменить, на всех копиях базы данных (разработка и производство), поэтому никакой другой игрок или дизайнер не может изменить его. , Затем он будет работать с базой данных разработки до тех пор, пока не будет завершен новый проект, и тогда изменения будут объединены с производственной базой данных, и эти активы будут зарегистрированы / разблокированы во всех средах.

Редактирование проигрывателя будет работать почти таким же образом, за исключением того, что роли базы данных / файловой системы будут поменяны местами - они работают с производственной базой данных, и все обновления загружаются в dev после завершения.

Блокировка актива может быть ограничена свойствами, в которых вы хотите гарантировать отсутствие конфликтов: в Примере 1 вы заблокируете, ID 123456как только игрок начнет его создавать, поэтому разработчикам не будет назначен этот ID. В Примере 2 ваши разработчики заблокировали имя сценария assignFrenchAccentво время разработки, поэтому игрок должен был бы выбрать другое имя при разработке своей модификации (эта небольшая неприятность может быть уменьшена пространством имен, но это само по себе не позволит избежать конфликтов, если вы не дадите пользователь / разработчик конкретного пространства имен, и тогда у вас возникнет та же проблема с управлением пространствами имен). Это означает, что вся разработка должна считываться из одной онлайновой базы данных, но все, что вам требуется от этой базы данных в этих примерах, это имена объектов, поэтому производительность не должна быть проблемой.

С точки зрения реализации, достаточно иметь единую таблицу со всеми ключами и состоянием активов (доступно, заблокировано из dev, заблокировано из prod), синхронизировано / доступно в реальном времени в разных средах. Более сложное решение будет реализовывать полную систему контроля версий - вы можете использовать существующую систему, такую ​​как CVS или SVN, если все ваши ресурсы находятся в файловой системе.

SkimFlux
источник
Обычно блокировать какие-либо данные на глобальном уровне непрактично - игроки могут редактировать мир просто с помощью обычной игры, и вы не хотели бы, чтобы эта игра мешала дизайнерам работать. Если вы разрешите глобальные блокировки, то операция слияния - это, по сути, операция перезаписи, которая проста - но если у вас нет глобальных блокировок, что тогда?
Kylotan
Как упомянул lathomas64, ответ будет зависеть от того, о каких данных вы говорите. Без глобальных блокировок я бы подумал, что вам понадобится система контроля версий и набор правил для разрешения любых конфликтов - эти правила будут зависеть от требований к данным и игровому процессу. Я думаю, что после слияния каждое слияние сводится к простой операции перезаписи.
SkimFlux
0

Я думаю, что дело здесь в том, чтобы четко принять вашу ответственность. 1) Сервер сообщает, что в настоящее время приемлемо, и API для доступа. База данных изменяется в соответствии с определенными правилами. 2) Создателям разрешено создавать контент, но он должен воспроизводиться после обновлений. Это исключительно ваша ответственность: любое обновление должно быть в состоянии анализировать старые структуры данных, желательно как можно более чистыми и простыми.

Идея «Маунт-Пойнт» имеет свои преимущества, если вы заинтересованы в отслеживании уникальных предметов и позиций внутри гибкой структуры, особенно если мы признаем, что вся «домашняя» структура игрока претерпит кардинальные изменения, и вы хотите сохранить это немного деко в своих шкафчиках.

Это очень сложный вопрос, удачи! Там, вероятно, не существует ни одного ответа.

karmington
источник
0

Я не думаю, что это большая проблема, как вы делаете это.

Я бы просто переписал созданные пользователем моды, предупредив, что «Mod X может работать некорректно с этой версией», оставив создателям модов изменить свою работу. Я не думаю, что это нереалистичное ожидание, что обновления могут отключить определенные моды.

То же самое для контента, созданного пользователем, просто сделайте резервную копию и перезаписать.

У меня нет реального опыта в этом, просто вносить предложения.

Вуди Занцингер
источник
Я думаю, что если бы это было чисто для пользовательских модов, то вы были бы правы. Но некоторые игры явно касаются контента, созданного пользователем, и поэтому вы не можете просто уничтожить его.
Kylotan
Затем просто оставьте место в системе для контента, который вы можете добавить позже. Если вы используете идентификационные номера, зарезервируйте 1-1000. Или, если пользователи могут называть свои активы, не позволяйте пользователям начинать имя с «FINAL-» или чего-то другого (зарезервируйте его для своих собственных активов). РЕДАКТИРОВАТЬ: или еще лучше, сделать это в обратном порядке, заставляя пользовательский контент в диапазоне или префиксе
Вуди Zantzinger