tac
> Но тут есть варианты.
«Entia non sunt multiplicanda praeter necessitatem» (с)
сложность хранения и манипуляции данных должна быть обоснована
greencrazycat
> сложность хранения и манипуляции данных должна быть обоснована
учитывая, что в худшем (крайне маловероятном) случае , если за время отсутствия игрока, другие игроки перетрогают ВСЕ камни в мире, то объем обработки тонкого сервера станет равен объему обработки толстого сервера (хотя и даже тогда, тонкий сервер будет выигрывать, т.к. не парсит сообщения от клиента ... а клиент выполнит парсинг максимум за тоже время, что и прием состояния с сервера (там же все равно надо парсить)) ... такая сложность кажется оправданной.
> другие игроки перетрогают ВСЕ камни в мире
=
> сервер рассказал Пете что в мире есть камни которые лежат по координатам ... (массив данных)
и только в первый раз он получит весь список
Спасибо, всем за дискуссию ... начну делать ) убедил сам себя )
(Пока я отдаю себе отчет, что это справедливо для небольших карт, а потом подумаем про "чанки")
robotcity
> и конечно же можно будет создать скрипт который будет нагружать твой сервер,
> создать огромное количество записей в бд, перекладывая камень с места на место
Видимо таки да - нужно вот что уточнить:
1. идентификация сущностей важна - не должен меняться ID после изменения места (путешествия по миру, если только это не создание вещи заново - хотя и тут есть момент. Дерево и поваленное дерево - это разные деревья? наверно да ... а дерево с установленным скворечником - когда скворечник можно то снять, то прикрепить? ... пффф - тут надо думать )
2. сервер может сам затирать не актуальную инфу, про вещь с определенным ID (но не интересуясь что это за информация (не парся тело сообщения) )
tac
> правильно я понял, что есть чанка? набор камней вокруг игрока скажем на радиус его видимости * koef, где koef - запас на движение и обновление.
чанк - это кусок карты, ячейка в 2д сетке.
> 1. идентификация сущностей важна - не должен меняться ID после изменения места
> (путешествия по миру, если только это не создание вещи заново - хотя и тут есть
> момент. Дерево и поваленное дерево - это разные деревья? наверно да ... а
> дерево с установленным скворечником - когда скворечник можно то снять, то
> прикрепить? ... пффф - тут надо думать )
Возьмем пример с деревом, если ты его повалил и сменил ID, то тебе придется передать два сообщения: 1- старый ID "дерево удален", 2- появился новый ID "поваленное дерево", проще не менять ID при каждом чихе, а передать что старое ID сменило статус со "стоячее дерево" на "лежачее дерево". А вообще тебе виднее, ты только про камни говорил, а теперь деревья и скворечники полезли.
> 2. сервер может сам затирать не актуальную инфу, про вещь с определенным ID (но не интересуясь что это за информация (не парся тело сообщения) )
Если сервер что то затирает то это уже не логи, меняется название меняется подход.
Дальше что то понять сложно, что ты делаешь, какую игру, если у тебя карта высот и там можно таскать камни и рубить деревья то это один вид оптимизаций, причем можно неплохо сжать все данные и передавать небольшие куски, если же ты как в RUST или FOREST хочешь строить многоитажки то это совсем другая история. Да и карту высот надо будет все равно хранить на сервере, без нее многое не получится сделать.
robotcity
> Если сервер что то затирает то это уже не логи, меняется название меняется подход.
Согласен. Подход несколько изменил благодаря дискуссии, но основа тем не менее осталась - не авторитарный сервер, а толстый клиент, хотя сервер сейчас упрощает многое для клиента.
----------------------------------------------------------------------------------------------------------------------------
Решение планируется использовать для Конструктора выживания (Survival Сonstructor)
более подробное описание находится в документе: http://cyberrise.eu/Share/CyberKernel.pdf (раздел Сетевое решение)
Выдержка из документа, относящиеся к теме ...
Состояния объектов и их иерархия в игровом мире
В данном решении используется философия «толстого клиента», что означает, что на сервере не происходит ни анализа, ни обработки бизнес-логики. Но сервер, обладая базой данных хранит текущие состояние игрового мира. Чтобы клиентам было удобно обновлять сведения о игровом мире, состояние каждого объекта обновляются отдельно. Под объектом может пониматься любая модель персонажа, вещи, здания, природы и всего того, что не является статичным на все время игры и с чем персонажи или боты могут взаимодействовать или изменять.
Клиент должен обеспечить уникальность идентификатора объекта (ObjectID) на все время игры. Значения ObjectID должны быть больше 10 (первые 10 идентификаторов зарезервированы). Настоятельно рекомендуется не менять идентификатор при изменении координат объекта в мире или помещении его в инвентарь, или агрегации его в более объемлющий объект. И только при физическом уничтожении объекта или необратимом его изменении, когда он теряет свои свойства, приобретая другие (например, дерево было срублено) сообщать серверу, что объект уничтожен (указать параметр идентификации иерархии HID = -1). В случае же таких изменений, которые являются обратимыми (например, к дереву присоединен желобок и ведро, для получения сока) следует использовать параметр идентификации иерархии HID, указав идентификатор объекта, который является объемлющим. Инвентарь или нахождение предметов в руках персонажа при этом является частным случаем применения иерархии, когда объемлющим объектом является персонаж.
Синхронизация объектов у разных клиентов
Само состояние объектов сервером как было сказано не анализируется и просто хранится в виде строки текста, которую формирует клиент при изменении состояния. При наличии онлайн других клиентов сервер рассылает им сообщения, принятые от клиента, который поменял состояние объекта. Каждый из клиентов принимая сообщение от сервера сам его анализирует и синхронизирует у себя соответствующие объекты.
При этом, настоятельно рекомендуется каждому клиенту поддерживать свое локальное состояние игрового мира с помощью базы SQLite, сохраняя там состояния всех объектов, полученные от сервера. Таким образом, когда игрок отключится от сети (закончит играть) его локальное состояние будет соответствовать тому времени, когда он отключился. Когда же он снова подключится к игре, чтобы загрузить состояние игрового мира он запросит с сервера изменения только с того момента как его не было в игре, сможет обновить свое локальное состояние игрового мира и воссоздать актуальную сцену. Такой подход, только в самом худшем случае, когда за время отсутствия игрока случилось так, что другие игроки изменили ВСЕ объекты, будет получать состояния всех объектов, а как правило будет получать информацию лишь об измененных объектах, что ускоряет начальную загрузку состояния игрового мира.
Так же следует отметить, что пока объект находится в иерархии (HID ≠ 0) нет необходимости следить за его состоянием, и только в том случае, когда он выбирается из иерархии он продолжает “самостоятельную жизнь” в игровом мире и обладает самостоятельным состоянием. Таким образом, по умолчанию объекты, находящиеся в иерархии, не синхронизируются и игнорируются при загрузке текущего состояния игрового мира. Есть лишь одно исключение в случае загрузки для тех предметов, которые находятся в иерархии самого персонажа. Если же необходимо следить за состоянием объекта, находящегося в иерархии, то идентификатор HID нужно умножить на -1. Так, например, это может быть оправдано для предметов находящихся в руках персонажей, к ним по-прежнему нет доступа у других персонажей, но при смене предмета в руке другие персонажи могут видеть, что держит персонаж.
tac
интересно как ты будешь конфликты разгребать, даже git такое автоматом не может, к примеру я схватил камень бросил его и попал человеку в голову который упал со скалы и потянул за собой цепочку событий, а оказалось что у другого клиента просто пинг длинный и камень он взял раньше и кинул в другого человека и убил его, внимание вопрос как все это разгрести?
UPD. я почему то подумал что ты хочешь сделать по аналогии elite:dangerous с его P2P и поэтому задал глупый вопрос. Как я понял у тебя все равно будет сверка с сервером на каждое действие и конфликтов не будет, только лаги, но это уже стандартная проблема.
robotcity
вопрос правильный, в документе есть раздел про сетевую задержку ... поэтому клиент знает когда событие реально случилось, и сможет это развести ..
tac
База вообще никак не относится к синхронизации мира. База - это сугубо хранение данных, чтобы когда ты рестартуешь свой сервер - восстановить некоторое состояние.
В общем случае у тебя есть класс мира, который проводит все симуляции и рассчеты которые необходимы, с учетом всех правил этого мира. Точно такой же класс мира крутится у тебя на клиенте.
то есть буквально и на клиенте и на сервере у тебя есть объект:
class World { //blablabla }
За счет этого происходят достаточно точные предсказания. Но из-за лагов миры могут рассинхронизироваться, и поэтому, скажем раз в секунду, ты отсылаешь стейт объектов вокруг игрока, которые неплохо было бы синхронизировать. Ну и с максимальной частотой отсылаешь информацию о других игроках. Клиент же серверу посылает только действия.
Как видишь - никакой базы данных тут нет. А база данных нужна только если ты планируешь сохранять состояние мира после рестарта сервера. Например для таких игр как CS, Dota2 и т.п., где есть система матчей - во время боя никакой базы вообще нет. Только по результатам боя рейтинг записывается в базу. Если это MMORPG - то любое изменения состояния игроков само собой заносится в базу. Но это совершенно никак не связано с сетевым кодом. То есть приходит у тебя action от клиента "переместиться в точку XY", этот экшн обрабатывается твоим World, и World скажем в каком-то коллбеке сообщает, что у объекта N теперь новая позиция XY, ну и этот колбек обрабатывает класс, работающий с БД.
robotcity
> с его P2P
не, прямого взаимодействия между клиентами и не предполагалось, просто минимизация действий на сервере
MrShoor
Этот стандартный прием я понимаю. Но он мне по ряду причин не нравится. Поэтому описываю тут свой велосипед. (скоро пойду делать, но решил проговорить в слух)
1. База, говоря о сервере, мы подразумеваем СУБД, а она может (и даже предпочтительнее в ряде случаев), чем класс World, программу которого надо запускать на сервере. В СУБД просто пишутся хранимые процедуры и запускаются по таймеру или при реакции на клиента. Единственный минус - процедурное программирование вместо объектного. Но для обработки массивов данных SQL пригоден лучше. Поэтому база это не просто хранение в случае авторитарного сервера, могут быть варианты. Но это частности.
2. Но как можно увидеть из описания предлагаемого подхода - "на сервере не происходит ни анализа, ни обработки бизнес-логики". Тем самым серверное решение становится универсальным и не зависимым от задачи/игры. И такой аспект достаточно важен.
3. Нагрузка на сервер/скорость - я уже называл этот аргумент, очевидно если правила игры обрабатываются у клиентов, то нагрузка на сервер становится на порядок меньше. И собственно это отличие описано в документации Юнити https://docs.unity3d.com/ru/current/Manual/net-HighLevelOverview.html , сравнивая авторитарный и не-авторитарный сервер ... (мое же решение является в чем смесью их)
4. Не особо хотел забегать вперед, но при предлагаемом решении действительно есть особенности при программировании собственно правил мира. Скажем так, в ряде простых игр, этих правил собственно и нет .. в шутерах вообще бегают только игроки и стреляют, в сурвивалах - есть крафт и взаимодействие с миром, и то о чем мы говорили тут выше про камни. А правила мира возникают, только при наличии NPC с их AI, и такие вещи как погода и прочие. Тогда возникает вопрос - если нет сервера, то кто будет двигать NPC. И тут возникают два варианта решения:
4.1. На сервере запустить клиента (в котором можно отключить камеру, и графический режим), но в режиме без игрока. Там и будут ходить NPC, которые по правилам других управляемых игроками персонажей, будут ровно так же слать сообщения на сервер ... и по сути такого клиента можно запускать в любом месте сети, просто такой клиент будет обеспечивать работу правил мира, но к сетевому взаимодействию все это не относится.
4.2. А если подумать, то вариант 4.1. можно представить как распределенные вычисления у клиентов. И тогда каждый играющий онлайн, возьмет на себя часть нагрузки по управлению NPC, а оставшись играть один мы получим автоматически режим сингла и функции варианта 4.1. будет выполнять оставшийся клиент. А если отключится последний игрок - то мир замрет (а зачем его гонять, когда никто не играет :) )
tac
> В СУБД просто пишутся хранимые процедуры и запускаются по таймеру или при реакции на клиента.
> Но для обработки массивов данных SQL пригоден лучше.
Это тормозилово и лагалово будет, ибо задача базы - обеспечить целостность транзакций. Даже крутые mmorpg не пишут в базу напрямую, весь мир крутится отдельно, примерно как я описал, а новые состояния объектов пишутся в отдельном потоке в базу. Все потому что SQL база - это медленно, когда нужно проводить много мелких одиночных транзакций. А для реалтайм игры оно так и будет.
tac
> И такой аспект достаточно важен.
Ага, ровно до тех пор, пока ты не получишь лагающее нечто, а получишь ты его с таким подходом сразу же.
tac
> Нагрузка на сервер/скорость - я уже называл этот аргумент, очевидно если
> правила игры обрабатываются у клиентов, то нагрузка на сервер становится на
> порядок меньше.
Привет читеры? 2016 год на дворе. Правила у клиентов должны обрабатываться только для того, чтобы клиент меньше замечал рассинхронизацию.
tac
> На сервере запустить клиента (в котором можно отключить камеру, и графический
> режим), но в режиме без игрока.
Да, примерно этот вариант. Только это вариант шиворот на выворот. По хорошему должен быть сервер, с миром без графики. А у клиента - просто надстройка над кодом мира, которая умеет рисовать графику. Т.е. не выключаем графику для сервера, а наоборот добавляем графику в клиент, а на сервер добавляем работу с БД.
tac
> И тогда каждый играющий онлайн, возьмет на себя часть нагрузки по управлению
> NPC, а оставшись играть один мы получим автоматически режим сингла и функции
> варианта 4.1.
Реализовать сложно, и опять привет читеры.
MrShoor
> Привет читеры
этот аргумент уже встречался выше .. я его отложил, но давайте обсудим ..
что надо сделать читеру, чтобы вмешаться в работу клиента? Дизассемблировать код, угадать какой mov ответственен за изменения позиции бота и его поменять ? Не слишком ли сложно для читеров :)
tac
> что надо сделать читеру, чтобы вмешаться в работу клиента? Дизассемблировать
> код, угадать какой mov ответственен за изменения позиции бота и его поменять ?
> Не слишком ли сложно для читеров :)
Отследить какой участок памяти хранит здоровье например. Менять его внешним кодом на максимальное всегда, и обеспечить себе бессмертие.
Далеко ходить не надо, вот хороший пример: https://www.youtube.com/watch?v=jZq1f2gfzGo
MrShoor
> SQL база - это медленно, когда нужно проводить много мелких одиночных
> транзакций. А для реалтайм игры оно так и будет.
это смотря как её использовать. Есть скажем две задачи:
1. Управлять поведением бота AI в мире
2. Рассчитать тем-ру тела всех персонажей при наступлении вечера
В первом случае придется применить "4.1. На сервере запустить клиента", а во втором будет самое то, применить SQL по таблице состояний.
Тема в архиве.