Using wallet data to unlock inventory items

  1. Versions: Nakama 3.9.1, Docker, Unreal SDK
  2. Server Framework Runtime language: TS

I’m trying to do the following logic to update player inventory after a player purchases a certain item.

  1. Player unlocks item using in game coin
  2. Client sends an RPC with payload which includes the item and index of the item which was unlocked ( eg: unlocked 3rd item in frames)
  3. Server gets notified of the purchase using RPC
  4. Gets how much the item costs from inventory collection using the data inside payload
  5. Updates wallet by reducing no of coins from step 4
  6. Return if purchase was successful.

I can update the wallet manually by hard coding a value on the server, but the client fails to send the payload from the client and thereby I can’t read from storage to update it.

Sorry I’m a bit lost at your issue.

the client fails to send the payload from the client and thereby I can’t read from storage to update it.

What does ‘fail’ mean? Is there an error? Code snippets would also be helpful.

We are have implemented in game currencies using wallets, we also have unlockables like banners, and display avatars which are stored in storage collections. when a player unlocks a certain unlockable(say banner 3), the client sends a wallet update request( which I made an RPC) which updates the wallet using the value of banner 3.

I’m assuming that the client sends a payload where it specifies the artifact he unlocked and the index of the unlockable so that the RPC function can fetch the value of the unlockable from the database using storage reads and update all the fields accordingly(reduce coins in wallet, set the artifact as unlocked).

Where I’m stuck is, the client doesn’t send any data to the server, it only calls the RPC function and doesn’t have any payload attached to it.

Example payload: "{\"artifact\":\"banner\",\"index\":3}"

@SnappierSoap318 Can you show me how you are actually calling the RPC in your code? Code examples and client/server logs would be very helpful.

@mofirouz Sorry for the late reply,
This is the client side code

void UBackendGameinstance::updateWallet(FString Artifact, int32 index)
{
	client->rpc(session,
		"updateWallet",
		"{\"artifact\": \"playerBanner\", \"index\": 3, \"coinsToRemove\" : 10}"
                // for testing if package works
	);
}

On server side:

initializer.registerRpc("updateWallet", updateWallet); // inside initializer

//RPC function
let updateWallet: nkruntime.RpcFunction = (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama
) => {
  let user_id = ctx.userId;
  let artifact: string = ctx.queryParams;
  logger.info(String(artifact));
};

@mofirouz should i be using real time clients instead of normal client to transfer RPC?

This looks good - a couple of questions;

  • On server startup, in the server logs, do you see a log line that says the function “updateWallet” was found and registered as a RPC?

  • On the client, can you do a try-catch of any errors and log the error, if any?

yes, it does register and shows up in the logs.

Client does not show any errors

@SnappierSoap318 The problem is that your TypeScript function misses the actual payload parameter in the function head to get the payload which you can interact with. Your code should look like:

let updateWallet: nkruntime.RpcFunction = (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  payload: string
) => {
  let user_id = ctx.userId;
  let artifact: string = ctx.queryParams;
  logger.info(payload);
};

Hope this helps.