В данной теме разберём серверные и клиентские пакеты, а так же структуру кеша магазина.
Структура серверных пакетов магазина
Для построения списка товаров, предметов и их связей используются пакеты:
Свернуть ↑
Предметы зарегистрированные в магазине.
Код:
// int всего предметов
// int предметов в этой партии
// int количество отправленных предметов
foreach {
// int itemId
// byte ItemAuthType (см. ниже)
// byte ItemExpirationType (см. ниже)
// byte всегда 2 ?
// byte необходимый уровень звания или достижения
// byte ограничение: 0 - нет, 1 - достижение, 2 - звание
// short идентификатор достижения
}
// int уникальный идентификатор магазина
Свернуть ↑Развернуть ↓
Свернуть ↑
Товары зарегистрированные в магазине.
Код:
// int всего товаров
// int товаров в этой партии
// int количество отправленных товаров
foreach {
// int goodsId
// byte всегда 1 ?
// byte 1, 2, 4 ?
// int стоимость в поинтах
// int стоимость в донат монетах
// int всегда 0 ?
// byte SaleType (см. ниже)
// byte[39] // не исползуется
}
// int уникальный идентификатор магазина
Свернуть ↑Развернуть ↓
Свернуть ↑
Предметы которые можно восстанавливать, может игнорироваться в различных регионах.
Код:
// int всего предметов
// int предметов в этой партии
// int количество отправленных предметов
foreach {
// int itemId
// int стоимость восстановления 1% в поинтах
// int стоимость восстановления 1% в донат монетах
// int максимальная прочность (100)
}
// int уникальный идентификатор магазина
Свернуть ↑Развернуть ↓
Свернуть ↑
Пакет связывает предметы с товарами.
Код:
// int всего связей
// int связей в этой партии
// int количество отправленных связей
foreach {
// int goodsId
// int itemId
// int прочность, количество или время в секундах для приобретаемого предмета
// int всегда 0
}
// int уникальный идентификатор магазина
Свернуть ↑Развернуть ↓
Начиная с 3 версии клиент стал кешировать полученные данные в файл Shop.dat.
Структура кеша Shop.dat
Код:
// int уникальный идентификатор магазина
// int количество товаров
// int количество предметов
// int количество восстанавливаемых предметов
// int количество связей
// byte[количество товаров * 58]
// byte[количество предметов * 11]
// byte[количество восстанавливаемых предметов * 16]
// byte[количество связей * 16]
Для проверки актуальности данных клиент отправляет пакет PROTOCOL_SHOP_GET_SAILLIST_REQ (1029) c md5 хешем файла Shop.dat и в ответ ожидает PROTOCOL_SHOP_GET_SAILLIST_ACK (1030) со следующей структурой:
Код:
bool // true если кеш отличается от актуального
int // дата последней проверки в формате yyMMddhhmm
Если хеш отличается, то необходимо отправить 4 пакета описанные ранее.
Примеры работы с данными
Рассмотрим пример добавления товара включающем в себя
SG 550 Ext. с ограничением по количеству боёв. Я буду использовать json, вы же можете использовать xml или базу данных.
Свернуть ↑
class Item
{
public int Id { get; set; }
public ItemAuthType Type { get; set; }
public ItemExpirationType ExpirationType { get; set; }
public byte Unk { get; set; }
public bool Repairable { get; set; }
public int RepairPoints { get; set; }
public int RepairCash { get; set; }
public ItemRestrictionType RestrictionType { get; set; }
public byte AchievementOrTitleLevel { get; set; }
public short AchievementId { get; set; }
}
Code: C#
enum ItemAuthType : byte
{
None,
Expirable,
Temporal,
Permanent,
PcCafeRegular,
PcCafePremium,
Special
}
Code: C#
enum ItemExpirationType : byte
{
None,
Durable,
Temporary,
Permanent
}
Code: C#
enum ItemRestrictionType : byte
{
None,
Achievement,
Title
}
Code: C#
Свернуть ↑Развернуть ↓
Свернуть ↑
class Goods
{
public int Id { get; set; }
public byte Unk1 { get; set; } = 1;
public byte Unk2 { get; set; } = 1;
public SaleType SaleType { get; set; } = SaleType.Regular;
public int Points { get; set; }
public int Cash { get; set; }
public ICollection<GoodsItemMatching> Matching = new HashSet<GoodsItemMatching>();
}
Code: C#
enum SaleType : byte
{
Regular,
LatestOffer,
BestSeller,
Event,
PCCafe,
Discount
}
Code: C#
class GoodsItemMatching
{
public int GoodsId { get; set; }
public int ItemId { get; set; }
public int Quantity { get; set; }
}
Code: C#
Свернуть ↑Развернуть ↓
Обратите внимание на идентификатор товара (
10300101), он состоит из ItemId * 100 + n (есть исключения, но об этом как-то в другой раз), это необходимо для группировки предметов, дальше вы поймёте о чём я.
После отправки пакетов в магазине появится 1 товар на 100 боёв стоимостью в 10000 очков.
Теперь разберёмся с группировкой. Если добавить второй товар с идентификатором 1030010
2 и тем же предметом, но отличающимся ценой или количеством, то у пользователя появится возможность выбора предмета:
Свернуть ↑
Код:
[
{
"Id": 10300101,
"SaleType": "Regular",
"Points": 6000,
"Matching": [
{
"ItemId": 103001,
"Quantity": 50
}
]
},
{
"Id": 10300102,
"SaleType": "Regular",
"Points": 10000,
"Matching": [
{
"ItemId": 103001,
"Quantity": 100
}
]
}
]
Свернуть ↑Развернуть ↓
Результат.
Также вместо количества боёв - мы может указать количество дней в секундах (86400 * n дней), ниже в примере предмет на 7 дней.
Пока всё, буду дописывать по мере появления желания.
Появились вопросы и дополнения касательно магазина PB - пожалуйста, пишите их в этой теме.