Sending User Data Along with Teleports

I’m teleporting players (1-by-1) between multiple experiences which all belong to the same Roblox group and I would like to send some data along while teleporting.
Specifically send player earned coins from one experience to another experience when teleporting to it.

Is this possible?

I’m reading:

and it says:
If your experience utilizes secure user data like in-experience currency or inventory, implement data stores or memory stores to maintain data from place to place.

But those stores are only shared between places of the same experience, right!?

How is it possible to send data over while teleporting to another experience, or fetch it from somewhere secure after teleporting?

Thanks in advance for any pointers!

1 Like

You could set up an external server (e.g. in Python) to store the data and use HttpService, however this is very complex for a basic need. Otherwise, you’ll have to send it normally, and risk exploiters being able to modify the data (such as making 200 coins into 20000000 coins).

There’s methods out there to cryptographically sign data, however they aren’t proven to be reliable so I would be careful if I were to take that route.

1 Like

Thanks for the solution and you are right setting up an external server would be an overkill right now.

But I think the 2nd one is a good enough for now idea. So you are suggesting to use:

To send basic non-secure data from place to place, call TeleportOptions:SetTeleportData() before passing it to TeleportAsync().

and also use some cryptography to “scramble” the data.

Thanks for the link I’ll check it out.

Wait, I’m sorry, I found a much better solution for this. You can use Player:GetJoinData()! It has the benefit of being guarenteed of being sent from a Roblox server, not client. There’s just one small issue, it only guarentees the data was sent from a Roblox server in the last 48 hours. So a exploiter could earn 200 coins and get teleported, then reteleport over, and over again with those 200 coins which means they can can duplicate coins. This is obviously bad.

However, you could send a nonce (number used once), and the reciever would store that nonce and make sure that nonce doesn’t appear again. Here’s an example utilizing Memory Store Service:

Sending Server Side:

local HttpService = game:GetService("HttpService")

local coins = 200

local teleportOptions = Instance.new("TeleportOptions")
teleportOptions:SetTeleportData({
    ["coins"] = coins,
    ["nonce"] = HttpService:GenerateGUID(false):lower()
})

Even though we’re using HttpService, we’re not sending any HTTP requests, only generating a GUID (e.g. ff4f3e92-506a-4e8d-9184-54e3ac3846fe). We don’t need to worry about getting duplicate GUIDs, the chances are so incredibly low.

On the receiving side, we need to check if the nonce has been used before, and then mark it as being used before. So, something like this would work:

local MemoryStoreService = game:GetService("MemoryStoreService")
local Players = game:GetService("Players")

local nonceMap = MemoryStoreService:GetSortedMap("nonceMap")

Players.PlayerAdded:Connect(function(player)
	local teleportData = player:GetJoinData()["TeleportData"]
	
	if nonceMap:GetAsync(teleportData["nonce"]) then
		player:Kick("duplicated teleport data! please try again.")
		return
	end
	
	nonceMap:SetAsync(teleportData["nonce"], player.UserId, 172800)
	
	print(teleportData["coins"])
end)

I haven’t tested this code, so tell me if something doesn’t work quite right (ik publishing your games to test is very annoying)

I hope this helps!

2 Likes

Thank you very much @TreeBen77 for following up.
That nonce (number used once) is a really good idea.

What I implemented in the end was:

  • sending over the coin amount (encrypted with a key both experiences know in a server script, so use it to encrypt before teleporting and decrypt the amount after GetJoinData() at target experience)
  • send also the UserID over to make sure the proper player receives the coins when GetJoinData() is called (I did this because I guessed that maybe there can be some issue if many players are joining at the same time or teleporting over)
    And in my case when teleporting I set the coin amount to 0 in the datastore right before teleporting, so I believe I don’t need the “nonce (number used once)” solution as the hacker will not be able to teleport again along with the same amount of coins, as their coin amount is now 0 in that experience.
    Is that right?

No, when the exploiter is teleporting, they can grab the teleport info, with the data to give coins. Then they rejoin your experience and teleport again using the same teleport data. And your receiving game will be none the wiser, because it thinks it came from the server.

Remember, Roblox only guarantees join data is:

  • sent from the listed SourceGameId
  • for the listed player
  • for your experience
  • sent in the last 48 hours.

You should also make just the SourceGameId is actually allowed to send data, otherwise don’t trust it.

1 Like

I searched for SourceGameId in the documentation but did not find anything, but then found info about it here: GetJoinData now includes SourceGameId
Thanks for all the help! I’ll add that check.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.