Player Inventory
##1. 什么是玩家背包 ? 玩家背包旨在帮助您管理玩家的游戏内物品 。您可以查看和跟踪玩家在其库存中购买和收到的物品。出于安全原因,我们仅为DS和虚拟服务器提供将物品授予库存的 API。您也可以转到门户 -> 玩家直接将物品授予玩家。
2. 物品实例当物品被授予或被玩家购买并存放在背包以供日后使用时,该物品将被实例化为物品实例。只有普通物品和容器物品才能被实例化。 物品实例通过物品ID与物品关联。
您可以在PGOS SDK的FItemInstance结构中找到物品实例的详细定义。
- instance_id:玩家背包栏中物品实例的唯一标识符。
- amount:对于不可堆叠的物品,数量始终为1。对于可堆叠的物品,数量为大于或等于0的整数。
- status:实例状态,可以是Available、Expired、Revoked或Consumed*。
- 只有处于Available状态的实例才会通过GetInventoryItemInstances API返回给客户端。
- 当实例过期时,其状态更改为Expired。
- 当实例被删除时,其状态更改为Revoked。
- 当实例被使用时,其状态变为 Consumed。
- item:从物品继承的属性集。
- mutable_custom_data:物品实例的可变自定义数据( key-value对),可由服务器设置或增加。可变自定义数据键前缀必须是“flt_”、“int_”和“str_”之一,表示值的类型为
float
、int
或string
。每个键的最大长度为 128,值的最大长度为 4096。 key-value对的最大数量为 32。 - mutable_custom_data_version:可变自定义数据的版本,每次自定义数据更改时都会增加。
- tags:物品实例的标签( key-value对),可由客户端或服务器设置。每个 key 的最大长度为 128,value 的最大长度为 1024, key-value对的最大数量为 32。
- created_time:该道具实例的创建时间。
- updated_time:该道具实例的更新时间。
- expired_time:该道具实例的过期时间戳。
- time_to_live:该道具实例在玩家背包中保留的时间,单位为秒。 下图展示了实例化和实例状态转换过程:
3. 在门户网站中使用玩家背包
3.1 查看背包
前往门户网站 -> 玩家并找到目标玩家。在玩家详情的经济标签页中,您可以查看玩家的背包。背包显示了该玩家拥有的物品实例。在此页面中,您可以:
- 按物品实例状态筛选显示的物品实例。
- 通过物品ID或实例ID搜索物品实例。
- 在玩家背包中放置游戏内物品。
- 撤销物品实例。
3.2 发放物品
在某些情况下,您可能需要直接在玩家背包中发放游戏内物品。前往管理后台 -> 玩家,找到目标玩家并打开玩家背包。点击+发放游戏内物品并设置要发放的物品。
您可以一次性发放多种类型的物品,并为每种类型指定数量:
3.3 日志
PGOS 会记录所有玩家背包操作的日志,以便您轻松追踪游戏经济中的物品流向和玩家的经济活动。前往管理后台 -> 玩家,找到目标玩家,进入经济页面,点击日志。点击日志 ID 可查看详细信息:
日志 ID:日志的唯一标识。
关联日志 ID:某些背包操作会与其他操作相关联,因此需要记录关联的日志 ID。这类操作包括但不限于:
开启从容器获得的物品
通过礼包发放物品
操作:操作类型,可以是发放、开启、消耗、撤回或过期。
物品实例:被操作的对象。例如:
- 当操作 = 发放时,这是被发放的物品实例。
- 当操作 = 开启时,这是被开启的容器物品实例。
创建时间:日志的创建时间。
4. 使用客户端 SDK 访问背包
4.1 获取玩家背包
此操作获取玩家背包中的所有物品实例,包括可用和已过期的物品实例。
接口原型:
/**
* Get all item instances in the player's inventory.
*/
void GetInventory(TFunction<void(const FPgosResult& Ret, const FItemInstPack* Data)> Callback) const;
struct FItemInstPack
{
/** Item instances in the pack. */
TArray<FItemInstance> insts;
/** In-game item defines that may be referenced in the 'item_content', and you can use 'ItemDict::FindItem' to search. */
FItemDict item_dict;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetClientEconomyAPI();
if (Economy)
{
Economy->GetInventory([](const FPgosResult& Ret, const FItemInstPack* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetInventory Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetInventory Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2 消耗物品实例
该操作消耗玩家背包中的一个物品实例。每次消耗数量为1。此API仅适用于属性为"ItemType=Normal"的物品实例。
接口原型:
/**
* Consume the specified item instance in the player's inventory.
*
* The virtual server bound to the consumer action will be triggered.
*
* @param Params Request params.
*/
void ConsumeInstance(
const FClientConsumeInstanceParams& Params,
TFunction<void(const FPgosResult& Ret, const FClientConsumeInstanceResult* Data)> Callback) const;
struct FClientConsumeInstanceParams : public FBaseBackendEventParams
{
/** The item instance id. */
FString instance_id;
/**
* [Optional] Used to ensure the idempotence of the function. Idempotence means that regardless of how many times the function is called, the result remains the same.
* By passing a unique `idempotency_token`, it ensures that the function does not produce duplicate side effects or results when called repeatedly.
* Note: To avoid generating the same idempotency_token as other players, it is recommended to concatenate it with the player's own player ID.
*/
FString idempotency_token;
};
struct FClientConsumeInstanceResult : public FClientInstanceOperationResult
{
/** The error code returned by the virtual server bound to the consumer action. */
int32 custom_err_code = 0;
/** The error msg returned by the virtual server bound to the consumer action. */
FString custom_err_msg;
/** The json string returned by the virtual server bound to the consumer action. */
FString func_result;
/**
* Whether the request is replayed.
* When it is True, it indicates that the result of the function is obtained by replaying with the same `idempotency_token`.
* This means that the result of the function has been generated in a previous call and is being reused in the current call.
*/
bool replayed = false;
};
struct FBaseBackendEventParams
{
/**
* [Optional] A game-defined custom value pass to PGOS backend event.
* If you need to get a custom value in the event, pass it in, otherwise, ignore this field.
* The size is limited to 4096 bytes (after converting the string to utf8 format).
* Detail for PGOS backend event: https://pgos.intlgame.com/pgosdoc/manual/service_manual/extensions/event.html.
* Detail for how to reference the 'event_custom_data':https://pgos.intlgame.com/pgosdoc/manual/service_manual/extensions/virtual_server_v2.html#43-the-request-and-response-protocol.
*/
FString event_custom_data;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetClientEconomyAPI();
if (Economy)
{
FClientConsumeInstanceParams Params;
Params.instance_id = TEXT("0e888750eb0444e2b5877f8e3e17c2d7");
// Params.idempotency_token = "player id" + "_" + "timestamp"
Economy->ConsumeInstance(Params, [](const FPgosResult& Ret, const FClientConsumeInstanceResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("ConsumeInstance Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("ConsumeInstance Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3 打开容器实例
此操作用于打开玩家背包中"Type=Container"类型的物品实例。每次操作打开数量为1。此API仅适用于具有"ItemType=Container"属性的物品实例。
接口原型:
/**
* Open the specified container instance in the player's inventory.
*
* The PGOS backend events `event_item_revoked` and `event_item_granted`/`event_currency_changed` will be triggered.
*
* @param Params Request params.
*/
void OpenContainerInstance(
const FClientOpenContainerInstanceParams& Params,
TFunction<void(const FPgosResult& Ret, const FClientOpenContainerResult* Data)> Callback) const;
struct FClientOpenContainerInstanceParams : public FBaseBackendEventParams
{
/** The container instance id. */
FString instance_id;
};
struct FClientOpenContainerResult : public FClientInstanceOperationResult
{
/** The item instances obtained after opening the container. */
FItemInstPack item_insts;
/** The currencies obtained after opening the container. */
TArray<FCurrency> currencies;
};
struct FClientInstanceOperationResult
{
/** The instance id of this operation. */
FString instance_id;
/** The number of instance remaining after this operation. */
int32 left_amount = 0;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetClientEconomyAPI();
if (Economy)
{
FClientOpenContainerInstanceParams Params;
// fill Params
Economy->OpenContainerInstance(Params, [](const FPgosResult& Ret, const FClientOpenContainerResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OpenContainerInstance Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OpenContainerInstance Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.4 撤销物品实例
此操作用于撤销玩家背包中的物品实例。
接口原型:
/**
* Revoke the specified item instance in the player's inventory.
*
* The PGOS backend event `event_item_revoked` will be triggered.
*
* @param Params Request params.
*/
void RevokeInstance(
const FClientRevokeInstanceParams& Params,
TFunction<void(const FPgosResult& Ret, const FClientInstanceOperationResult* Data)> Callback) const;
struct FClientRevokeInstanceParams : public FBaseBackendEventParams
{
/** The item instance id. */
FString instance_id;
};
struct FClientOpenContainerResult : public FClientInstanceOperationResult
{
/** The item instances obtained after opening the container. */
FItemInstPack item_insts;
/** The currencies obtained after opening the container. */
TArray<FCurrency> currencies;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetClientEconomyAPI();
if (Economy)
{
FClientRevokeInstanceParams Params;
// fill Params
Economy->RevokeInstance(Params, [](const FPgosResult& Ret, const FClientInstanceOperationResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("RevokeInstance Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("RevokeInstance Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.5 设置物品实例标签
更新玩家背包中指定物品实例的 tags
数据。
实例 tags
最多可以有32个键,每个键限制为128字节,每个值限制为1024字节(以窄字符串形式)。
接口原型:
/**
* Update the `tags` data of the specified item instance in the player's inventory.
* Instance `tags` can have up to 32 keys, with each key limited to 128 bytes and each value limited to 1024 bytes(in a narrow-character string).
*
* @param Params Request params.
*/
void SetInstanceTags(
const FClientSetInstanceTagsParams& Params,
TFunction<void(const FPgosResult& Ret, const FClientSetInstanceTagsResult* Data)> Callback) const;
struct FClientSetInstanceTagsParams
{
/** The item instance id. */
FString instance_id;
/** Update the data of the specified keys in the `tags`. If the key does not exist, it indicates inserting new data. */
TMap<FString, FString> update_data;
/** Delete the data of specified keys in the `tags`. The key from `update_data` cannot be included. */
TArray<FString> delete_keys;
};
struct FClientSetInstanceTagsResult
{
/** Latest `tags` of item instance. */
TMap<FString, FString> tags;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetClientEconomyAPI();
if (Economy)
{
FClientSetInstanceTagsParams Params;
// Fill params
Economy->SetInstanceTags(Params, [](const FPgosResult& Ret, const FClientSetInstanceTagsResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceTags Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceTags Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
5. 使用服务器 SDK 管理物品实例
5.1 发放物品实例
此操作将指定的游戏内物品发放给指定玩家。
接口原型:
/**
* Grant specified items to the player's inventory.
*
* The PGOS backend events `event_item_granted`/`event_currency_changed` will be triggered.
*
* @param Params Request params.
*/
void GrantItemToPlayer(
const FServerGrantItemToPlayerParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerGrantItemResult* Data)> Callback) const;
struct FServerGrantItemToPlayerParams : public FBaseBackendEventParams
{
/** The player id who will be granted items to. */
FString player_id;
/** The items will be granted. */
TArray<FServerGrantItem> items;
/**
* [Optional] Used to ensure the idempotence of the function. Idempotence means that regardless of how many times the function is called, the result remains the same.
* By passing a unique `idempotency_token`, it ensures that the function does not produce duplicate side effects or results when called repeatedly.
* Note: To avoid generating the same idempotency_token as other players, it is recommended to concatenate it with the `player_id`.
*/
FString idempotency_token;
};
struct FServerGrantItem {
/** The id of the item will be granted. */
pgos::pstring item_id;
/** The number of the item will be granted. */
uint32_t amount = 0;
/**
* The mutable kv data of the instance.
* The key must be prefixed with "int_", "flt_", or "str_", which respectively indicate that the value type is integer, float, or string.
* Max 32 keys, each key limited to 128 bytes and each value limited to 4096 bytes(in a narrow-character string).
*/
pgos::pmap<pgos::pstring, KVDataValue> mutable_custom_data;
};
struct FServerGrantItemResult
{
/** The player id who has been successfully granted. */
FString player_id;
/** The item instances that have been granted. */
FItemInstPack item_insts;
/** The currencies that have been granted. (such as granting bundle that contains currencies) */
TArray<FCurrency> currencies;
/**
* Whether the request is replayed.
* When it is True, it indicates that the result of the function is obtained by replaying with the same `idempotency_token`.
* This means that the result of the function has been generated in a previous call and is being reused in the current call.
*/
bool replayed = false;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetServerEconomyAPI();
if (Economy)
{
FServerGrantItemToPlayerParams Params;
// Fill Params
Economy->GrantItemToPlayer(Params, [](const FPgosResult& Ret, const FServerGrantItemResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GrantItemToPlayer Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GrantItemToPlayer Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
5.2 批量撤销实例
您可以批量撤销玩家背包中指定的物品实例。
接口原型:
/**
* Batch revoke the specified item instances in the player's inventory.
*
* The PGOS virtual server event `event_item_revoked` will be triggered.
*
* @param Params Request params.
*/
void BatchRevokeInstances(
const FServerBatchRevokeInstancesParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerBatchRevokeInstancesResult* Data)> Callback) const;
struct FServerBatchRevokeInstancesParams : public FBaseBackendEventParams
{
/** The player whose item instance will be revoked from inventory. */
FString player_id;
/** The item instance ids. Maximum array size: 99. */
TArray<FString> instance_ids;
};
struct FServerBatchRevokeInstancesResult
{
/** The number of instance remaining after this operation. key: item instance id, value: left amount. */
TMap<FString, int32> left_amounts;
/** Item instances that failed to revoke. key: item instance id, value: failed reason. */
TMap<FString, FPgosResult> fails;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetServerEconomyAPI();
if (Economy)
{
FServerBatchRevokeInstancesParams Params;
// Fill Params
Economy->BatchRevokeInstances(Params, [](const FPgosResult& Ret, const FServerBatchRevokeInstancesResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchRevokeInstances Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchRevokeInstances Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
5.3 搜索玩家背包
您可以通过实例ID在背包中搜索物品实例。如果实例ID参数为空,则返回玩家的整个背包。
接口原型:
/**
* Query item instances in the specified player's inventory.
*
* @param PlayerId The specified player id.
* @param InstanceIds Item instance ids to query. If the 'instance_ids' is empty, it will return all instances in the player's inventory.
*/
void GetPlayerInventory(
const FString& PlayerId,
const TArray<FString>& InstanceIds,
TFunction<void(const FPgosResult& Ret, const FServerGetPlayerInventoryResult* Data)> Callback) const;
struct FServerGetPlayerInventoryResult
{
/** The player id whose inventory will be queried. */
FString player_id;
/** The item instances of the query instance ids. */
FItemInstPack item_insts;
/** The instance ids which was failed to query. */
TMap<FString, FString> fails;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetServerEconomyAPI();
if (Economy)
{
FString PlayerId;
TArray<FString> InstanceIds;
Economy->GetPlayerInventory(PlayerId, InstanceIds, [](const FPgosResult& Ret, const FServerGetPlayerInventoryResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerInventory Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerInventory Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
5.4 设置物品实例自定义数据
更新玩家背包中指定物品实例的 mutable_custom_data
。当 mutable_custom_data
发生任何变更时,其版本号 mutable_custom_data_version
也会随之更新。
PGOS 规定了 mutable_custom_data
的键格式:键必须以 "int"、"flt" 或 "str_" 为前缀,分别表示值的类型为整数、浮点数或字符串。
SetInstanceCustomData
和 SetInstanceCustomDataWithVersion
这两个 API 有一些区别,开发者可以根据需求选择使用:
- 调用
SetInstanceCustomData
时,无需提供物品实例中mutable_custom_data
的版本,直接更新数据。 - 调用
SetInstanceCustomDataWithVersion
时,必须提供物品实例中mutable_custom_data
的最新版本,否则无法更新数据。
实例 mutable_custom_data
最多可以有 32 个键,每个键限制为 128 字节,每个值限制为 4096 字节(以窄字符串计)。
接口原型:
/**
* Update the `mutable_custom_data` of the specified item instance in the player's inventory.
* The key must be prefixed with "int_", "flt_", or "str_", which respectively indicate that the value type is integer, float, or string.
* Instance `mutable_custom_data` can have up to 32 keys, with each key limited to 128 bytes and each value limited to 4096 bytes(in a narrow-character string).
*
* @param Params Request params.
*/
void SetInstanceCustomData(
const FServerSetInstanceCustomDataParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerSetInstanceCustomDataResult* Data)> Callback) const;
/**
* Update the `mutable_custom_data` of the specified item instance in the player's inventory.
* The key must be prefixed with "int_", "flt_", or "str_", which respectively indicate that the value type is integer, float, or string.
* The 'version' that needs to be passed in can be obtained from the `mutable_custom_data` of the `ItemInstance`.
* If the 'version' passed in is the latest, the callback will return success along with the latest data after updated.
* If the 'version' passed in is not the latest, the callback will return failure(err_code=11108, kBackendKVDataVersionMismatched) along with the current latest data, you may try again with the latest version.
* Instance `mutable_custom_data` can have up to 32 keys, with each key limited to 128 bytes and each value limited to 4096 bytes(in a narrow-character string).
*
* @param Params Request params.
*/
void SetInstanceCustomDataWithVersion(
const FServerSetInstanceCustomDataWithVersionParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerSetInstanceCustomDataResult* Data)> Callback) const;
/**
* Batch update the `mutable_custom_data` of the specified item instance in the player's inventory.
* The key must be prefixed with "int_", "flt_", or "str_", which respectively indicate that the value type is integer, float, or string.
* Instance `mutable_custom_data` can have up to 32 keys, with each key limited to 128 bytes and each value limited to 4096 bytes(in a narrow-character string).
*
* @param Params Request params.
*/
void BatchSetInstanceCustomData(
const FServerBatchSetInstanceCustomDataParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerBatchSetInstanceCustomDataResult* Data)> Callback) const;
struct FServerSetInstanceCustomDataParams
{
/** The player whose item instance `mutable_custom_data` will be updated. */
FString player_id;
/** The item instance id. */
FString instance_id;
/** Update the data of the specified keys in the `mutable_custom_data`. If the key does not exist, it indicates inserting new data. */
TMap<FString, FKVDataValue> update_data;
/** Delete the data of specified keys in the `mutable_custom_data`. The key from `update_data` cannot be included. */
TArray<FString> delete_keys;
};
struct FServerSetInstanceCustomDataWithVersionParams : public FServerSetInstanceCustomDataParams
{
/** The latest `mutable_custom_data_version`. */
int32 version = 0;
};
struct FServerSetInstanceCustomDataResult
{
/** Latest `mutable_custom_data` of item instance. */
TMap<FString, FKVDataValue> mutable_custom_data;
/** Latest `mutable_custom_data_version` of item instance. */
int32 version = 0;
};
struct FServerBatchSetInstanceCustomDataParams
{
/** The player whose item instance `mutable_custom_data` will be updated. */
FString player_id;
/**
* The item instances to be updated. key: item instance id, value: custom data to be updated.
* Maximum map entries: 99.
*/
TMap<FString, FServerUpdatedInstanceCustomData> data;
};
struct FServerUpdatedInstanceCustomData
{
/** Update the data of the specified keys in the `mutable_custom_data`. If the key does not exist, it indicates inserting new data. */
TMap<FString, FKVDataValue> update_data;
/** Delete the data of specified keys in the `mutable_custom_data`. The key from `update_data` cannot be included. */
TArray<FString> delete_keys;
};
struct FServerBatchSetInstanceCustomDataResult
{
/** Latest `mutable_custom_data` of item instance. key: item instance id, value: latest custom data */
TMap<FString, FServerInstanceCustomData> data;
/** Item instances that failed to update. key: item instance id, value: failed reason. */
TMap<FString, FPgosResult> fails;
};
struct FServerInstanceCustomData
{
/** Latest `mutable_custom_data` of item instance. */
TMap<FString, FKVDataValue> mutable_custom_data;
/** Latest `mutable_custom_data_version` of item instance. */
int32 version = 0;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetServerEconomyAPI();
if (Economy)
{
FServerSetInstanceCustomDataParams Params;
// Fill params
Economy->SetInstanceCustomData(Params, [](const FPgosResult& Ret, const FServerSetInstanceCustomDataResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceCustomData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceCustomData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
void SomeUObjectClass::SomeFunction2()
{
auto Economy = IPgosSDKCpp::Get().GetServerEconomyAPI();
if (Economy)
{
FServerSetInstanceCustomDataWithVersionParams Params;
// Fill params
Economy->SetInstanceCustomDataWithVersion(Params, [](const FPgosResult& Ret, const FServerSetInstanceCustomDataResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceCustomDataWithVersion Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceCustomDataWithVersion Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
void SomeUObjectClass::SomeFunction3()
{
auto Economy = IPgosSDKCpp::Get().GetServerEconomyAPI();
if (Economy)
{
FServerBatchSetInstanceCustomDataParams Params;
// Fill Params
Economy->BatchSetInstanceCustomData(Params, [](const FPgosResult& Ret, const FServerBatchSetInstanceCustomDataResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchSetInstanceCustomData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchSetInstanceCustomData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
5.5 增加实例自定义数据
对实例的 mutable_custom_data
kvdata 执行原子递增操作。仅支持带有 "int" 和 "flt" 前缀的键。
实例的 mutable_custom_data
最多可以有32个键,每个键限制为128字节,每个值限制为4096字节(以窄字符串形式)。
接口原型:
/**
* Perform atomic increment operation on `mutable_custom_data` kvdata for the instance. [Only keys with the prefixes "int_" and "flt_" are supported]
*
* @param Params Request params.
*/
void IncrInstanceCustomData(
const FServerIncrInstanceCustomDataParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerIncrInstanceCustomDataResult* Data)> Callback) const;
struct FServerIncrInstanceCustomDataParams
{
/** The player id whose item instance `mutable_custom_data` will be updated. */
FString player_id;
/** The item instance id. */
FString instance_id;
/** Increments to update, key: kvdata key, value: increment of the value. */
TMap<FString, FKVDataValue> increments;
/**
* [Optional] Used to ensure the idempotence of the function.
* By passing a unique `idempotency_token`, it ensures that the function does not produce duplicate side effects or results when called repeatedly.
*/
FString idempotency_token;
};
struct FServerIncrInstanceCustomDataResult
{
/** Latest `mutable_custom_data` of item instance. */
TMap<FString, FKVDataValue> mutable_custom_data;
/** Latest `mutable_custom_data_version` of item instance. */
int32 version = 0;
/**
* Whether the request is replayed.
* When it is true, it indicates that the previously used `idempotency_token` was used, and the increment operation did not take effect. The result returns the latest `mutable_custom_data` and `mutable_custom_data_version` of the instance.
*/
bool replayed = false;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetServerEconomyAPI();
if (Economy)
{
FServerIncrInstanceCustomDataParams Params;
// Fill params
Economy->IncrInstanceCustomData(Params, [](const FPgosResult& Ret, const FServerIncrInstanceCustomDataResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("IncrInstanceCustomData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("IncrInstanceCustomData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
5.6 设置物品实例标签
更新玩家背包中指定物品实例的 tags
数据。
实例 tags
最多可以有32个键,每个键限制为128字节,每个值限制为1024字节(以窄字符串形式)。
接口原型:
/**
* Update the `tags` data of the specified item instance in the player's inventory.
* Instance `tags` can have up to 32 keys, with each key limited to 128 bytes and each value limited to 1024 bytes(in a narrow-character string).
*
* @param Params Request params.
*/
void SetInstanceTags(
const FServerSetInstanceTagsParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerSetInstanceTagsResult* Data)> Callback) const;
/**
* Batch update the `tags` data of the specified item instance in the player's inventory.
* Instance `tags` can have up to 32 keys, with each key limited to 128 bytes and each value limited to 1024 bytes(in a narrow-character string).
*
* @param Params Request params.
*/
void BatchSetInstanceTags(
const FServerBatchSetInstanceTagsParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerBatchSetInstanceTagsResult* Data)> Callback) const;
struct FServerSetInstanceTagsParams
{
/** The player id whose item instance `tags` will be updated. */
FString player_id;
/** The item instance id. */
FString instance_id;
/** Update the data of the specified keys in the `tags`. If the key does not exist, it indicates inserting new data. */
TMap<FString, FString> update_data;
/** Delete the data of specified keys in the `tags`. The key from `update_data` cannot be included. */
TArray<FString> delete_keys;
};
struct FServerSetInstanceTagsResult
{
/** Latest `tags` of item instance. */
TMap<FString, FString> tags;
};
struct FServerBatchSetInstanceTagsParams
{
/** The player id whose item instance `tags` will be updated. */
FString player_id;
/**
* The item instances to be updated. key: item instance id, value: tags to be updated.
* Maximum map entries: 99.
*/
TMap<FString, FServerUpdatedInstanceTags> data;
};
struct FServerUpdatedInstanceTags
{
/** Update the data of the specified keys in the `tags`. If the key does not exist, it indicates inserting new data. */
TMap<FString, FString> update_data;
/** Delete the data of specified keys in the `tags`. The key from `update_data` cannot be included. */
TArray<FString> delete_keys;
};
struct FServerBatchSetInstanceTagsResult
{
/** Latest `tags` of item instance. */
TMap<FString, FServerInstanceTags> data;
/** Item instances that failed to update. key: item instance id, value: failed reason. */
TMap<FString, FPgosResult> fails;
};
struct FServerInstanceTags
{
/** Latest `tags` of item instance. */
TMap<FString, FString> tags;
};
示例代码:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Economy = IPgosSDKCpp::Get().GetServerEconomyAPI();
if (Economy)
{
FServerSetInstanceTagsParams Params;
// Fill params
Economy->SetInstanceTags(Params, [](const FPgosResult& Ret, const FServerSetInstanceTagsResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceTags Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceTags Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
void SomeUObjectClass::SomeFunction2()
{
auto Economy = IPgosSDKCpp::Get().GetClientEconomyAPI();
if (Economy)
{
FClientSetInstanceTagsParams Params;
Economy->SetInstanceTags(Params, [](const FPgosResult& Ret, const FClientSetInstanceTagsResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceTags Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetInstanceTags Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
6. Key Errors Handling
Error Code | 相关 API | 处理建议 |
---|---|---|
kBackendGrantItemNumExceed | GrantItemToPlayer | 发放物品数量超出限制。 |
kBackendThrottling | GrantItemToPlayer ConsumeInstance OpenContainerInstance | 检测到当前玩家操作过于频繁,请稍后重试。 |
kBackendShouldRetry | GrantItemToPlayer | 失败的请求可以重试以获得成功。 |
kBackendIdempotentParamsMismatch | GrantItemToPlayer | idempotency_token 输入参数在操作中被重复使用,但至少有一个其他输入参数与之前的操作调用不同。现在当玩家 ID 不一致时将返回错误。 |
kBackendDupCustomDataKey | SetInstanceTags SetInstanceCustomDataWithVersion SetInstanceCustomData | 在更新数据和删除键中检测到重复的键,这可能导致不确定的行为。 |
kBackendInvalidCustomData | SetInstanceTags SetInstanceCustomDataWithVersion SetInstanceCustomData IncrInstanceCustomData | 自定义数据格式无效。自定义数据的前缀无效,或者键值长度、键的数量超出限制。 |