Skip to content

Commit

Permalink
fix(commerce): allow the server to refresh sku's after initial load
Browse files Browse the repository at this point in the history
- If users were to buy a new package while already in game this would still return that they didn't own the specified sku and it would stay like this until they rejoined, this isn't good user experience so instead we allow the server to refresh the skus once every 10 seconds
  • Loading branch information
AvarianKnight committed Jan 6, 2025
1 parent 6f5c264 commit c3cf69e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
12 changes: 11 additions & 1 deletion code/components/citizen-server-impl/src/ServerExtCommerce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,8 @@ class ClientExtCommerceComponent : public fwRefCountable
fx::Client* m_client;

bool m_commerceDataLoaded;

std::chrono::milliseconds m_lastUpdate { 0 };

std::set<int> m_ownedSkus;

Expand All @@ -481,11 +483,18 @@ void ClientExtCommerceComponent::LoadCommerceData()
{
auto userId = GetUserId();

if (m_commerceDataLoaded || !userId)
// If we already have our commerce data, only allow the server to refresh it every 10 seconds so we're not spamming requests
if (!userId || (m_commerceDataLoaded && (msec() - m_lastUpdate) < 10s))
{
return;
}

// Reset our commerce data state so we can properly wait for it to load again (in case this is a refresh)
m_commerceDataLoaded = false;
// don't allow the client to re-fetch while we're doing the request, this will be set again further down
// once the request is finished
m_lastUpdate = msec();

fwRefContainer<ClientExtCommerceComponent> thisRef(this);

HttpRequestOptions opts;
Expand Down Expand Up @@ -564,6 +573,7 @@ std::optional<int> ClientExtCommerceComponent::GetUserId()

void ClientExtCommerceComponent::SetSkus(std::set<int>&& list)
{
m_lastUpdate = msec();
m_ownedSkus = std::move(list);
m_commerceDataLoaded = true;
}
Expand Down
30 changes: 29 additions & 1 deletion ext/native-decls/LoadPlayerCommerceDataExt.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,36 @@ apiset: server
void LOAD_PLAYER_COMMERCE_DATA_EXT(char* playerSrc);
```
Requests the commerce data from Tebex for the specified player, including the owned SKUs. Use `IS_PLAYER_COMMERCE_INFO_LOADED` to check if it has loaded.
Requests the commerce data from Tebex for the specified player, including the owned SKUs.
Use [`IS_PLAYER_COMMERCE_INFO_LOADED_EXT`](#_0x1D14F4FE) to check if it has loaded.
This will not automatically update whenever a client purchases a package, if you want to fetch new purchases you will need to call this native again.
This native will temporarily cache the players commerce data for 10 seconds, a call to this native after 10 seconds will re-fetch the players commerce data.
## Parameters
* **playerSrc**: The player handle
## Examples
```lua
RegisterNetEvent("doesOwnPackage", function(packageIdSku)
-- source isn't valid across waits, so we localize it
local source = source
-- input isn't right
if type(packageIdSku) ~= "number" then
return
end
-- The native will cache the results
LoadPlayerCommerceDataExt(source)
-- Wait for the players data to load
while not IsPlayerCommerceInfoLoadedExt(source) do
Wait(0)
end
-- Tell the client if they own the package or not
TriggerClientEvent("doesOwnPackage", source, DoesPlayerOwnSkuExt(source, packageIdSku))
end)
```

0 comments on commit c3cf69e

Please sign in to comment.