Shops
packets8 packets
What a shop is offering (GenericListXtCommManager, item.ItemXtCommManager.shopListResponse).
Shops have no message of their own: clicking one asks for a generic list by the shop's id (gl), and the reply names the list's type. The types below are the ones the client builds a shop window from; every other type (localization, media, avatars, pets) shares the same head and is left unread here, so watching this packet never misreads one.
A shop list carries definition ids only. What each item costs, whether it is members only and which colours it comes in live in the item definitions the client loads at startup (ItemXtCommManager.getItemDef), not in this message.
Hearing and sending packets
What the game sends is heard on phantom.packets.client, and what the server sends on phantom.packets.server. watch hears a packet after it has gone through; on hears it first and may change or drop it; send sends one to that end. See Packets.
Overview
| Packet | Command | Way | What it is |
|---|---|---|---|
ShopListRequest | gl | game → server | The player asks for a shop’s contents. |
ShopList | gl | server → game | The server sends a shop’s contents. |
DenShopUpdateRequest | dsu | game → server | The player adds, reprices or removes items in their own den shop. |
DenShopUpdateResult | dsu | server → game | The server answers a change to the player’s own den shop. |
DenShopInfoRequest | dsi | game → server | The player asks to see a den shop’s listings. |
DenShopInfoResult | dsi | server → game | The server sends a den shop’s listings. |
DenShopBuyRequest | dsb | game → server | The player buys an item from a den shop. |
DenShopBuyResult | dsb | server → game | The server answers a den shop purchase. |
ShopListRequest
Asks for a generic list by its id (GenericListXtCommManager.requestGenericList, which ItemXtCommManager.requestShopList calls for a shop):
%xt%o%gl%<room>%<listId>%
The client answers itself from _cachedResponses the second time a list is asked for, so this is sent once per list per session.
Fields
| Field | Type | |
|---|---|---|
listId | number | The generic list's id: for a shop, the shop's id. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.ShopListRequest, (packet) => {
console.log(packet.listId);
});ShopList
A generic list (GenericListXtCommManager.handleNewData):
%xt%gl%<room>%<listId>%<listType>%<titleStrId>%<unused>%<diamondBundle>%<diamondCost>%<body>...%
For a plain shop the body is a count and that many definition ids. For a combined list (1060) it is a count of groups, the groups' types as one comma separated field, how many ids each takes as another, and then all the ids in that order.
int(...) in the client is 0 for a field that is not a number, which is what the bundle's cost is in every shop but the bundle shop; cost follows that rather than refusing the message.
Fields
| Field | Type | |
|---|---|---|
listId | number | The list's id, the one asked for in shop.list-request. |
listType | number | The list's type, such as 1000 for clothing (SHOP_LIST_TYPE). |
kind | "items" | "combined" | "other" | Which shape the list has: items for a shop that is a plain list of ids, combined for a combined list (1060), other for a generic list that is not a shop's. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.ShopList, (packet) => {
console.log(packet.listId, packet.listType, packet.kind);
});DenShopUpdateRequest
The player changes their own den shop's listings (ShopToSellXtCommManager.requestStoreUpdateItems):
%xt%o%dsu%<room>%<storeInvId>%<state>% <upsertCount>%<itemKind,invIdx,currencyType,cost>...% <removeCount>%<itemKind,invIdx>...%
Adding an item and repricing one already listed are sent the same way, as one list of upserts; only taking an item down is sent apart, named by its kind and inventory index alone. state is the shop's own version token, from the last den-shop-info or den-shop-update-result; a stale one is how the server refuses a change made against a shop that has moved on since.
Fields
| Field | Type | |
|---|---|---|
storeInvId | number | The stand: its den item's place in the player's den items. |
state | string | The shop's version token, from the last den-shop-info or den-shop-update-result. |
upserts | DenShopUpsert[] | Items added or repriced, as one list. |
removals | DenShopRemoval[] | Items taken down. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.DenShopUpdateRequest, (packet) => {
console.log(packet.storeInvId, packet.state, packet.upserts);
});DenShopUpdateResult
The server answers a den shop change (ShopToSellXtCommManager.onDenStoreUpdate):
%xt%o%dsu%<room>%<ok>%<state>%
state is only sent when ok, and is the shop's new version token: what the next change or den-shop-buy-request against this shop must send back. A change the server refused (a stale state, most often) carries no state.
Fields
| Field | Type | |
|---|---|---|
ok | boolean | Whether the change took. |
state | string | The shop's new version token; empty when the server refused the change. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.DenShopUpdateResult, (packet) => {
console.log(packet.ok, packet.state);
});DenShopInfoRequest
Asks to see a den shop's listings, the player's own or someone else's (ShopToSellXtCommManager.requestStoreInfo):
%xt%o%dsi%<room>%<userName>%<storeInvId>%
Fields
| Field | Type | |
|---|---|---|
userName | string | The shop's owner. |
storeInvId | number | The owner's den room this shop belongs to. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.DenShopInfoRequest, (packet) => {
console.log(packet.userName, packet.storeInvId);
});DenShopInfoResult
A den shop's listings (ShopToSellXtCommManager.onDenStoreInfo):
%xt%o%dsi%<room>%<ok>%<itemCount>%<state>%<items>...%
itemCount is -1 for a shop the server has nothing for, which carries no state and no items. Each item is currencyType, cost, itemKind, invIdx, defId, then more fields naming its look, whose shape depends on itemKind and, oddly, on whether this is the player's own shop: the server leaves them out for the player's own items, since the client already has them from its own inventory (ShopToSellXtCommManager.onDenStoreInfo, the forMyself branches). That is not something a message on its own says, so items is kept as read, unparsed; phantom.denShop decodes it, since it always knows which shop it asked for.
Fields
| Field | Type | |
|---|---|---|
ok | boolean | Whether the server has this shop. |
itemCount | number | How many items it lists; -1 for a shop the server has nothing for. |
state | string | The shop's version token; empty when itemCount is -1. |
items | string[] | Every item, unparsed; empty when itemCount is -1. See the type's own comment. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.DenShopInfoResult, (packet) => {
console.log(packet.ok, packet.itemCount, packet.state);
});DenShopBuyRequest
Buys an item from a den shop, the player's own or (the only case worth sending) someone else's (ShopToSellXtCommManager.requestStoreBuy):
%xt%o%dsb%<room>%<userName>%<shopInvIdx>%<state>%<itemKind>%<invIdx>%<currencyType>%<cost>%
Fields
| Field | Type | |
|---|---|---|
userName | string | The shop's owner. |
shopInvIdx | number | The listing's place in the seller's shop. |
state | string | The shop's version token, from den-shop-info. |
itemKind | number | A DEN_SHOP_ITEM_KIND value. |
invIdx | number | The item's place in the seller's inventory. |
currencyType | number | A DEN_SHOP_CURRENCY value. |
cost | number | What the listing asks. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.DenShopBuyRequest, (packet) => {
console.log(packet.userName, packet.shopInvIdx, packet.state);
});DenShopBuyResult
The server answers a den shop purchase (ShopToSellXtCommManager.onDenStoreBuy):
%xt%o%dsb%<room>%<status>%<ownerUserName>%<storeInvId>%<rest>...%
status is 1 for a sale made; anything else refused it and carries nothing more. rest is the buyer's new inventory index, the shop's new state, what it cost and in which currency, what kind of item it was and its own definition id, then fields naming its look that depend on that kind, and last the buyer's new balance: phantom.denShop decodes it, since unpacking it needs the item's kind, which is itself one of these fields.
Fields
| Field | Type | |
|---|---|---|
status | number | 1 for a sale made; anything else refused it. |
ownerUserName | string | The seller; empty when the purchase was refused. |
storeInvId | number | The seller's den room this shop belongs to; -1 when the purchase was refused. |
rest | string[] | Everything after storeInvId, unparsed. See the type's own comment. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.DenShopBuyResult, (packet) => {
console.log(packet.status, packet.ownerUserName, packet.storeInvId);
});