Background:
I’m working on a game with infinite world generation.
I have a world generator that generates the map based on a TerrainKey string I feed it.
When the player gets to the edge of the map, they get teleported to another reserved server with a different TerrainKey. I’m basically trying to create a grid of reserved servers that players can walk through.
Each box is a Reserved Server
The ReservedServer’s grid coordinates are the TerrainKey. For example, a TerrainKey of “0,0” would be the center of the universe.
Problem:
It’s saying the place doesn’t exist.
The place I’m trying to teleport to is under the same game as the place I’m teleporting from.
It’s a group place.
This works perfectly fine:
game:GetService('TeleportService'):Teleport(5907815608,game.Players.dispeller)
For some reason, this doesn’t:
local reservedCode = WorldPosService.getReservedCodeAndID("0,0")
TeleportService:TeleportToPrivateServer(5907815608,reservedCode,Players)
Same exact PlaceId, but it’s telling me the place doesn’t exist.
Is this an internal bug with Roblox?
Thought process
These are the steps of how I’m trying to get things to work:
Player needs to teleport to specific TerrainKey
-
Get ReservedServer Access Code based off TerrainKey
a. If Access Code is cached, grab cached code
b. If not cached, grab from datastore
c. If not in datastore
– Reserve new server
– Store Reserve Server Access Code in datastore under TerrainKey
– Store TerrainKey in datastore under PrivateServerId
– return Reserve Server Access Code -
Teleport player to Terrain place Reserved Server using Access Code
When a new server starts up in the Terrain place:
- Get current TerrainKey based off game.PrivateServerId
a. Check datastore using PrivateServerId as key - Generate terrain based off TerrainKey
- Use TerrainKey when players get to edge of map
(teleport to specific adjacent TerrainKey)
Code:
This is a module for reserving servers, storing data to datastore, and teleporting players
-- WorldPosService
-- dispeller 2020
WorldPosService = {}
--[[
TerrainKey = "1,2"
function WorldPosService.getReservedCodeAndID(TerrainKey: string)
returns string ReservedCode, string ServerId
function WorldPosService.getTerrainKeyFromServerIdAsync(ServerId: string)
returns string TerrainKey
function WorldPosService:Teleport(Players,key)
]]
local Players = game:GetService("Players")
local TeleportService = game:GetService("TeleportService")
local DatastoreService = game:GetService("DataStoreService")
local DataStore = DatastoreService:GetGlobalDataStore()
local getReservedCodeAndIDCache = {}
function WorldPosService.getReservedCodeAndID(TerrainKey: string)
assert(type(TerrainKey)=="string","TerrainKey must be a string!")
if getReservedCodeAndIDCache[TerrainKey] then
return unpack(getReservedCodeAndIDCache[TerrainKey])
end
local data = DataStore:GetAsync(TerrainKey)
-- local reservedCode = data[1]
-- local serverID = data[2]
if data then
getReservedCodeAndIDCache[TerrainKey] = data
return data[1],data[2]
else
local code,serverID = TeleportService:ReserveServer(game.PlaceId)
DataStore:UpdateAsync(TerrainKey, function(oldData)
-- Returning nil cancels the write
if oldData then
code = oldData[1]
serverID = oldData[2]
return nil
end
-- Returning a value attempts to use this as the TerrainKey's new value
return {code,serverID}
end)
warn'did update!'
-- Make TerrainKey obtainable via game.PrivateServerId
local datastoreSetSuccess = false
local err
for tries=1,30 do
if not datastoreSetSuccess then
datastoreSetSuccess,err = pcall(function()
DataStore:SetAsync(serverID,TerrainKey)
end)
if not datastoreSetSuccess then
warn("DATASTORE ERROR: ",err)
wait(tries)
end
end
end
if not datastoreSetSuccess then
error("FAILED TO SET DATASTORE SERVERID ",serverID," TO TerrainKey ",TerrainKey)
end
return code,serverID
end
end
local getTerrainKeyFromServerIdAsyncCache = {}
function WorldPosService.getTerrainKeyFromServerIdAsync(ServerId: string)
if getTerrainKeyFromServerIdAsyncCache[ServerId] then
return getTerrainKeyFromServerIdAsyncCache[ServerId]
end
local TerrainKey = nil
for tries=1,5 do
TerrainKey = TerrainKey or DataStore:GetAsync(ServerId)
if not TerrainKey then
wait(tries)
end
end
if TerrainKey then
getTerrainKeyFromServerIdAsyncCache[ServerId] = TerrainKey
return TerrainKey
else
warn("Server with id ",ServerId," has not been generated!")
return false
end
end
function WorldPosService.getTerrainKey()
return WorldPosService.getTerrainKeyFromServerIdAsync(game.PrivateServerId)
end
function WorldPosService:Teleport(Players,key)
if type(Players)~="table" then
Players = {Players}
end
local reservedCode = WorldPosService.getReservedCodeAndID(key)
TeleportService:TeleportToPrivateServer(5907815608,reservedCode,Players)
end
return WorldPosService
I have a simple script that calls the actual teleportation for testing purposes:
TS = game:GetService('TeleportService')
WorldPosService = require(game.ServerStorage:WaitForChild("WorldPosService"))
script.Parent.Touched:Connect(function(hit)
local Char = hit.Parent
local Player = game.Players:GetPlayerFromCharacter(Char)
if Player then
WorldPosService:Teleport(Player,"0,0")
--TS:Teleport(5530161763,Player)
Char.Humanoid:UnequipTools()
Char:Destroy()
wait(5)
if Player then
Player:LoadCharacter()
end
end
end)
Reply with any questions.
If you took the time to combe through the code yourself, but haven’t found any problems, reply anyway telling me so.
There’s always a small chance this is an internal bug with Roblox. It’s either that, or the Teleport Failed message is misleading; It says the place doesn’t exist, even though you can still teleport to the place without ReservedServers.