Работа с Player IO API part #4 - База данных (практика)

Настало время попрактиковаться. Начнём с основ и попробуем перейти к более сложным вещам. Однако раскрыть всю суть работы с базами данных в одном посте, к сожалению, не получится.

Попробуем выполнить различные операции с использованием обоих языков — AS3 и C#.

Работа со стандарной таблицей PlayerObject

Добавление объекта

PlayerObject таблица по умолчанию. И ключ объекта будет относиться к имени пользователя создавшего этот объект (имя пользователя указывается при соединении с Player IO сервером). Это значительно упращает работу с данной таблицей. Давайте попробуем загрузить таблицу во флеше и что-нибудь передать в качестве объекта.

AS3

private function handleConnect(client:Client) {
...
client
.bigDB.loadMyPlayerObject(function(playerObject:DatabaseObject):void{
       playerObject
.Name = "Noob";
       playerObject
.Pass = "xxx";
       playerObject
.save();
});
...
};


Получаем следующее:


Вложенность данных

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

AS3

private function handleConnect(client:Client) {
...
client
.bigDB.loadMyPlayerObject(function(playerObject:DatabaseObject):void{
       playerObject
.Name = "Noob";
       playerObject
.Pass = "xxx";
       playerObject
.Items = {item1:"sword",item2:"bow",item3:"gun"};
       playerObject
.save();
});
...
};


C#
public override void UserJoined(Player player){
           
...
            player
.PlayerObject.Set("Name", "Noob");
            player
.PlayerObject.Set("Pass", "xxx");
           
DatabaseObject items = new DatabaseObject();
            items
.Set("item1", "sword");
            items
.Set("item2", "bow");
            items
.Set("item3", "gun");
            player
.PlayerObject.Set("Items", items);
            player
.PlayerObject.Save();
           
...
};


Вот что получаем:


Ну а для того, чтобы изменить значение переменной вложенного объекта стоит обратиться к нему соответственно вот так:

AS3

private function handleConnect(client:Client) {
...
client
.bigDB.loadMyPlayerObject(function(playerObject:DatabaseObject):void{
       playerObject
.Items.item1 = "super_sword";
       playerObject
.save();
});
...
};


Работа с собственной таблицей

Добавление объекта с помощью AS3

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

AS3

private function handleConnect(client:Client) {
...
client
.bigDB.createObject("MyNewTable","NewObject",{"Name":"","Level":0});
...
};


В данном случае, в заранее созданную таблицу мы добавляем новый объект, и объявляем его переменные вот таким образом — {«Name»:"",«Level»:0}. Объявлять переменные не обязательно. Также не обязательно именовать созданный объект, однако, метод должен получить 3 аргумента. Если мы напишем в качестве имени объекта null, будет создан объект с ключём в виде уникального id. Если в качестве объявления переменных использовать null, будет создан пустой объект.

Также, метод позволяет добавлять callback и errorHandler функции после объявления переменных.

Добавление объекта с помощью C#

C#
public override void UserJoined(Player player){
     
...
     
var MyNewObj = new DatabaseObject();
     
MyNewObj.Set("Username", player.ConnectUserId);
     
PlayerIO.BigDB.CreateObject("LoginRegistration", player.ConnectUserId, MyNewObj, null);
     
...
};


Стоит заметить, что в C# варианте аргумент callBack ожидаемый. Передаём либо null, либо реальную ссылку. А вот errorHandler здесь также, не обязателен.

Удаление объектов с помощью AS3

В Player IO существует 2 метода удаления объектов. Первый метод удаляет указанный по ключам массив объектов; второй метод удаляет объекты в заданных границах используя индекс. В данном посте, методы работы с базой данных с использованием индексов рассмотрены не будут.

AS3

private function handleConnect(client:Client) {
...
client
.bigDB.deleteKeys("PlayerObjects",["guest176","guest45",username]);
client
.bigDB.deleteKeys("MyNewTable",["guest176"]);
...
};


Удаление объектов с помощью C#

C#
public override void UserJoined(Player player){
     
...
     
PlayerIO.BigDB.DeleteKeys("MyNewTable", new string[]{"MyObjectKey","MyObjectKey2"});
     
...
};


В обоих случаях, данным методом также удаляются объекты из стандартной таблицы PlayerObjects. Метод включает в себя не обязательные callback и errorHandler.

Загрузка объектов с помощью AS3

Загрузка объектов может быть произведена с использованием нескольких методов:

load() — загрузка объекта по указанному ключу из указанной таблицы.
loadOrCreate() — загрузка объекта по указанному ключу из указанной таблицы. Если объект отсутствует — будет создан новый объект с указанным ключём.
loadKeys() — загрузка объектов по указанным ключам из указанной таблицы.
loadKeysOrCreate() — загрузка массива объектов по указанным ключам из указанной таблицы. Если объекты отсутствуют — будут созданы новые объекты с указанными ключами.
Также существуют методы loadRange() и loadSingle(), с использованием индексов, которые, в данном посте, рассматриваться не будут. Про эти методы вы можете почитать в официальной документации Player IO здесь.

Так как эти методы практически аналогичны, рассмотрим для примера самый сложный — loadKeysOrCreate().

AS3

private function handleConnect(client:Client) {
...
client
.bigDB.loadKeysOrCreate("MyNewTable",["Admin","Moderator","monster1"],function(dbarr:Array):void{
dbarr
[0].Name = "cool";
dbarr
[1].Name = "must die";
dbarr
[2].Name = "big daddy";
for(var i:int=dbarr.length-1;i>=0;i--){
        dbarr
[i].save();
   
}
});
...
};


C#
public override void UserJoined(Player player){
     
...
     
PlayerIO.BigDB.LoadKeysOrCreate("MyNewTable", new string[] { "dedmoroz1", "dedmoroz2" }, delegate(DatabaseObject[] result)
           
{
                result
[0].Set("Name", "Pavel");
                result
[0].Save();
                result
[1].Set("Name", "Petrovich");
                result
[1].Save();
           
});
     
...
};


Получение ключа объекта

Для того, чтобы получить ключ объекта используем конструкцию типа:

AS3

DatabaseObject.key;


C#

DatabaseObject.Key;


На этом, о работе с БД, пока всё. Каким будет следующим шаг «осады крепости» под названием Player IO? =)
  • +5

Комментарии (29)

0
Меня вопрос мучает один, я, честно говоря не читал остальные статьи(кроме первой) так как времени не было, но все хочу этим заняться). Хотел бы узнать, какой ping у всей этой системы?
+2
Пинг системы целиком и полностью зависит от соединения с интернетом. Ну а там уже мелочи. Однако запись данных в базу данных — ассинхронный процесс. Это стоит учитывать. И с этим можно и нужно бороться. И с пингом кстате тоже.
0
спасибо за уроки. как приступлю к созданию мультиплеерной игрушки, начну изучение апи с твоих постов) правда в первой игрушке вряд ли буду использовать базы данных. сначала по-минимуму — локальное сохранение + таблица рекордов от мочи.
0
За уроки — пожалуйста:) Жду предложений о чём рассказать дальше) А насчёт использования БД. Смотри сам. Но если не хочешь чтобы в твоей игре, с одной стороны, были толпы читеров, а с другой — толпы недовольных этим, чесных игроков — то надо использовать БД хотябы по минимуму. Это совсем не сложно:)
0
оно то всё не сложно, но когда этого несложного накапливается, то становится уже черезчур) понятно, что БД это хорошо, но тогда придется еще делать регистрацию игроков, делать также возможность играть незарегистрированным, предусматривать в интерфейсе указания для чего нужна регистрация и т.п. плюс еще не совсем ясен вопрос со стоимостью сервиса. миллион объектов будут обходиться в 500$ в месяц.

вот кстати я подумал о чем мне интересно было бы почитать дальше: интересно как приблизительно прикинуть сколько траффика будет потреблять игра например при миллионе геймплеев. как это посчитать? хочется ведь прикинуть и расходы на этот замечательный сервис) возможно это очевидно и я просто не вижу леса за деревьями? :)
0
Насчёт БД — миллион объектов… В умелых руках — 25 000 объектов это огого! Тем уж более, я нигде не встречал описание ограничений на количество переменных в одном объекте. Проверял — 20 стринговых создаётся как нефиг делать)

А если примерно прикинуть — план FREE даёт нам 25 000 объектов, при том что максимальное количество игроков одновременно в онлайне 500 (в разных комнатах, которых должно быть минимум 10 при таком раскладе (45 игроков на 1 комнату)). Это даёт нам по 50 объектов на игрока. Даже если игроков зарегестрированных будет 1к или 2к — объектов всё ещё достаточно для нормальной работы. Однако, если зарегестрированных пользователей — овер 1к-2к — имхо надо уже начинать монетизироваться и переходить на план выше:) В случае оплаты 900 рублей в месяц, количество зарегестрированных пользователей можно поднять минимум в 10 раз.
Ещё один метод — удалять регистрации и объекты пользователя если тот не заходит более месяца например.

Миллион геймплеев. хм. Это помоиму просто не реально подсчитать. Для каждой игры — свой траффик. При этом, это сильно зависит от качества и количества обращений/соединений/записей/чтений :) Грамотно написанный код, думаю может уменьшить траффик на треть или даже на половину.

Если говорить на моём примере (это конечно ниразу не пример но всё же), при работе с их АПИ и постоянном тестировании, + чат лежал здесь (сейчас пришлось убрать), игра съела меньше 1 мб траффика за 1 месяц при позволенных 20 гигабайтах.
0
Однако, если зарегестрированных пользователей — овер 1к-2к — имхо надо уже начинать монетизироваться и переходить на план выше:)
Ага, вот это самое интересное — монетизация мультиплеера :) Даже если найти спонсора, то в отличии от одиночной игры, скорее всего прийдется поддерживать некоторое время, воевать с читерами, оплачивать сервер.
0
Тут ведь дело каждого. Если ты хочешь сделать онлайн игру в которую БУДУТ играть, надо будет готовится к тому, что придётся поддерживать проект. Как иначе. А если просто так — игра для фана — пакет фри за глаза.
0
Насчёт БД — миллион объектов… В умелых руках — 25 000 объектов это огого! Тем уж более, я нигде не встречал описание ограничений на количество переменных в одном объекте. Проверял — 20 стринговых создаётся как нефиг делать)
Я в курсе, что в один объект вставляется много переменных. И я расчитываю как раз, что на одного зарегистрированного игрока выделяется один объект, чтобы хранить его параметры и достижения, чтобы игрок мог потом залогиниться и продолжить. Неужели миллион зарегистрированных игроков это нереально много? :)
0
10,000,000 Objects
(0.03$ per additional 1,000)
0
мМне кажется миллион это много. Всё что больше миллиона — будет более полезным вешать на свой хостинг, писать полностью всё самому, нанимать людей для поддержки. Миллион зарегистрированных — думаю впринципе должно хватить на покушать:)
0
ну вешать на свой хостинг и писать собственный сервер это уже слишком много мороки. и при этом далеко не факт, что результат будет стабильно работать. лучше уж использовать player.io, как мне кажется — сэкономить время и нервы.

но я вообще говорил о другом. мне просто интересна оценка стоимости использования player.io для средне-успешных игр. немного настораживает то, что их почти не делают. раз в полгода появляется только одна игра типа shellshock и всё. так что информации по этому поводу вообще нет. т.е. пока делать не начнешь — не узнаешь во сколько это обойдется. а хотелось бы прикинуть заранее. ну хотя бы примерно. :) ладно, ничего страшного, посмотрим)
0
миллион объектов будут обходиться в 500$ в месяц.
Чо-то много… ММО писать собрался? :)

интересно как приблизительно прикинуть сколько траффика будет потреблять игра например при миллионе геймплеев.
А вот тут уже фиг посчитаешь… только делать и смотреть сколько там выходит трафика.

Мне вобще кажется, что они особо не экономили на размере пакетов, чтоб за трафик больше платили :) Одни строковые идентификаторы пакетов чего стоят :) Может хоть пакеты сжимают при отправке, а при получении расжимают.
0
Если пакеты не сжимать и не кодировать то что? правильно — ппц всей нашей игре.) Поэтому их кодируют. Насколько знаю — и сжимают тоже. На форуме кстате поднималась тема надёжности пакетов. Там вроде где-то было и про сжатие… Хотя быть может я и не прав, и они к этим пакетам ещё и шума кидают) Людей понять можно — кушать все хотят.)
0
Чо-то много… ММО писать собрался? :)
Я чуть выше ответил. Неужели миллион зарегистрированных игроков это много? :) Понятно, что многие из них просто залогинятся один раз через свой конговский и фб аккаунт для пробы, поиграют и больше заходить не будут. Но объект в БД то останется. Понятно, что можно раз в месяц удалять тех, кто не заходил в течении месяца. Но всё равно… Или я чего-то не понимаю в работе с БД?
0
Можно удалять и объекты из БД.

Подумал кстати вариант — человек не заходил месяц — можно данные из базы сбросить на диск (сериализовать например) и сохранить у себя на хостинге. Пользователя удалить или завести запись под тех кто уже был.
Если вдруг потом такой пользователь зайдет через полгода — восстановить его в базе.
0
Теперь надо писать статьи о синхронизации и лагокомпенсаторе :)
  • _dm_
  • _dm_
0
Там не так сложно. Пара методов универсальных, вроде бы. Наверное проще даже самим глянуть на офф сайте…

Есть идея написать простейшую игрушку, таки для примера.)
0
Не сказал бы, что так уж просто… смотря что синхронизировать и с каким пингом
0
нет нет. ты не так понял. Синхронизация БД нужна, например, когда стоит монстр в мморпг. и к нему подходят 2 игрока одновременно. с задержкой например в секунду. И не фаакт, что запрос о занятости объекта успеет дойди до серва а оттуда до всех клиентов чтобы не получилось жоского бага. На этот случай используют локинг. Но с этим я пока не знаком. Но там описывается всё одной функцией.

А высоченный пинг — победить невозможно. Поэтому лучше наверно принудительно разрывать соединение во избежание багов. А вообще, в реалтайм играх исопльзуется хитрый алгоритм предсказания движения игрока, для того чтобы движения были более плавными:)

Наверное когда подкоплю знаний о таких вот «трюках» — создам отдельный пост.)
0
Я имел в виду синхронизацию не БД, а игрового процесса. К примеру вот такие башни: получать от сервера передвижения всех монстров — жирно, надо считать локально, а раз локально, то начинается морока с float числами, которые надо менять на fixed, иначе рассинхрон ацкий — сам сталкивался…
Для топ-даун шутера там уже другое — интерполяция/экстраполяция объектов, как минимум
C физикой вобще адъ >_<
0
Ну на то мы и программисты — чтобы ПИСАТЬ двиги:) к каждой игре нужно приложить голову. Нет абсолютно универсального варианта.

Например — считать передвижения монстров — конечно на клиенте, но если игрок например стрельнул по нему или кликнул — посылаем запрос серверу — действительно ли он там. Ну в этом духе. Интерполяция наверное почти везде полезна. Теже рпг — если персонажи движутся по карте в реальном времени.

С физикой… ХЗ. Я не думаю что это всё настолько прям глобальные и нерешабельные проблемы. Все игры делают — значит можно:) главное не спамить на серв, а граммотно распределять ответственность — клиент/сервер.
0
Тут еще очень важна надежность клиента. Надежность флешевского клиента стремится к нулю.
0
Ммм. Возможно ты прав, но я не вижу здесь проблемы. Если сервер сайд описан грамотно, то от клиента мало что зависит (это я не в плане стабильности игрового процесса, а в плане глобальной системы). Если флеш у одного словил глюк — другие пользователи этого не узнают (не должны узнать).
0
Да дело не в глюках, а в преднамеренном изменении кода, для получения некой выгоды. Это касается любых ММО, но флеша в большей мере из-за его незащищенности. Т.е. обращаться на прямую к БД и создавать в ней какие либо объекты — идея не самая здравая, нужны обрабатываемые запросы. Вообще я читал статью немножко невнимательно, поэтому могу что либо недосмотреть. Сам хочу сделать небольшую РПГ для своего блога (в шапку блога воткнуть), для моих читателей.
+1
В этом плане я вроде уже говорил — у Player IO всё более или менее вменяемо — защищёность системы на том уровне, которого достаточно для флеша и даже для микротранзакций.

В БД данные других пользователей клиент тронуть не сможет — это раз. При изменении данных пользователя на серверной стороне мы должны буквально проверять и сохранять каждый пук игрока.

Ну вот я не могу представить сценария (детского) взлома из клиента. А если глабольно — читеры везде. И какой бы уровень защищённости не был бы. Для этого нужно модерировать хоть иногда)
0
Ну раз так, то все правильно:). А читеры есть и будут. Я сам много лет игры без читов не играл (первая, которую прошел без читов был manhunt).
0
А я вот читы не любил всегда:) разве что F1 и F3 на эмуляторах для сохранения и загрузки:)
+1
Я скорее из чистого любопытства их использовал. Типа а что будет если… Многие сам нашел. Много всяких игр распиливал в поисках кода для изменения чего либо в игре. Интернета не было, нового не было ничего, вот я старые игры и ковырял как мог.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.