
Работа с 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
- darkvam
Комментарии (29)
вот кстати я подумал о чем мне интересно было бы почитать дальше: интересно как приблизительно прикинуть сколько траффика будет потреблять игра например при миллионе геймплеев. как это посчитать? хочется ведь прикинуть и расходы на этот замечательный сервис) возможно это очевидно и я просто не вижу леса за деревьями? :)
А если примерно прикинуть — план FREE даёт нам 25 000 объектов, при том что максимальное количество игроков одновременно в онлайне 500 (в разных комнатах, которых должно быть минимум 10 при таком раскладе (45 игроков на 1 комнату)). Это даёт нам по 50 объектов на игрока. Даже если игроков зарегестрированных будет 1к или 2к — объектов всё ещё достаточно для нормальной работы. Однако, если зарегестрированных пользователей — овер 1к-2к — имхо надо уже начинать монетизироваться и переходить на план выше:) В случае оплаты 900 рублей в месяц, количество зарегестрированных пользователей можно поднять минимум в 10 раз.
Ещё один метод — удалять регистрации и объекты пользователя если тот не заходит более месяца например.
Миллион геймплеев. хм. Это помоиму просто не реально подсчитать. Для каждой игры — свой траффик. При этом, это сильно зависит от качества и количества обращений/соединений/записей/чтений :) Грамотно написанный код, думаю может уменьшить траффик на треть или даже на половину.
Если говорить на моём примере (это конечно ниразу не пример но всё же), при работе с их АПИ и постоянном тестировании, + чат лежал здесь (сейчас пришлось убрать), игра съела меньше 1 мб траффика за 1 месяц при позволенных 20 гигабайтах.
(0.03$ per additional 1,000)
но я вообще говорил о другом. мне просто интересна оценка стоимости использования player.io для средне-успешных игр. немного настораживает то, что их почти не делают. раз в полгода появляется только одна игра типа shellshock и всё. так что информации по этому поводу вообще нет. т.е. пока делать не начнешь — не узнаешь во сколько это обойдется. а хотелось бы прикинуть заранее. ну хотя бы примерно. :) ладно, ничего страшного, посмотрим)
А вот тут уже фиг посчитаешь… только делать и смотреть сколько там выходит трафика.
Мне вобще кажется, что они особо не экономили на размере пакетов, чтоб за трафик больше платили :) Одни строковые идентификаторы пакетов чего стоят :) Может хоть пакеты сжимают при отправке, а при получении расжимают.
Подумал кстати вариант — человек не заходил месяц — можно данные из базы сбросить на диск (сериализовать например) и сохранить у себя на хостинге. Пользователя удалить или завести запись под тех кто уже был.
Если вдруг потом такой пользователь зайдет через полгода — восстановить его в базе.
Есть идея написать простейшую игрушку, таки для примера.)
А высоченный пинг — победить невозможно. Поэтому лучше наверно принудительно разрывать соединение во избежание багов. А вообще, в реалтайм играх исопльзуется хитрый алгоритм предсказания движения игрока, для того чтобы движения были более плавными:)
Наверное когда подкоплю знаний о таких вот «трюках» — создам отдельный пост.)
Для топ-даун шутера там уже другое — интерполяция/экстраполяция объектов, как минимум
C физикой вобще адъ >_<
Например — считать передвижения монстров — конечно на клиенте, но если игрок например стрельнул по нему или кликнул — посылаем запрос серверу — действительно ли он там. Ну в этом духе. Интерполяция наверное почти везде полезна. Теже рпг — если персонажи движутся по карте в реальном времени.
С физикой… ХЗ. Я не думаю что это всё настолько прям глобальные и нерешабельные проблемы. Все игры делают — значит можно:) главное не спамить на серв, а граммотно распределять ответственность — клиент/сервер.
В БД данные других пользователей клиент тронуть не сможет — это раз. При изменении данных пользователя на серверной стороне мы должны буквально проверять и сохранять каждый пук игрока.
Ну вот я не могу представить сценария (детского) взлома из клиента. А если глабольно — читеры везде. И какой бы уровень защищённости не был бы. Для этого нужно модерировать хоть иногда)