Hello. I know that Roblox has service called TeleportService that allows players to teleport between places. But, there is a question: is it possible to teleport instances (parts, models, scripts etc. but bot players) between places using TeleportService (and additionally Instance.Parent)?
There’s an example where objects should be teleported to another place: here’s a train on a huge railway network (over a 1 million studs!) divided into several places; when train approaches the place border, it should be teleported to other place.
TeleportService can only teleport players and not parts.
If you’re insistent about doing this, I recommend looking into serialization. Basically when the train reaches the border, save its values (position, velocity, states and etc.) using memoryStores to load them into the other place.
Assuming the train you’re using is the same in all your places, I think it’s best to save stuff like velocity rather than the entire train.
- How to implement this?
- Should I change my mind that I decided to make things like “Teleport here for services to” at station?
This is possible through messagingservice and reflectionservice. reflectionservice will provide you a list of properties that an instance uses, and messagingservice can be used to tell servers to create the instance with the defined data. there is an issue with this though as messages can only be 1KB max, so even with buffer optimizations you may only be able to send 10-25 instances in a single message. there is also the issue of messaging limits that roblox imposes, but if you still want to make it, i have a semi-boilerplate example you can work off of. it is most likely the best thing you are going to get besides sending it to an external server
local RS = game:GetService("ReflectionService")
local ES = game:GetService("EncodingService")
local MS = game:GetService("MessagingService")
local Instances = {
"Part","Decal","Model"
}
local Query = table.concat(Instances,",") -- get instance query so we only grab valid instances from the thing we want to replicate
-- prepare the valid properties list so we only grab replicable properties
for i,v in ipairs(Instances) do
local Props = RS:GetPropertiesOfClass(v,{ExcludeDisplay = true}) -- this is readonly because reasons
local ValidProps = {}
local DefaultInstance = Instance.new(v)
for a = #Props,1,-1 do
local Val = Props[a]
local Char = string.sub(Val.Name,1,1)
if Val.Serialized == false or next(Val.Permits) == nil or string.lower(Char) == Char then
-- legacy property name, not serialized, or no read/write perms
continue
end
Val = table.clone(Val) -- readonly because reasons
table.insert(ValidProps,Val)
Val.Default = DefaultInstance[Val.Name] -- default value
end
Instances[v] = ValidProps
end
-- encoding instance data
local inst = workspace.Glasses -- example instance, this one is a model
local DescQuery = inst:QueryDescendants(Query) -- querydescendants handles everything linearly so it should be in order when constructed
table.insert(DescQuery,1,inst) -- insert the main parent item as the first index so it is made first
local ReplicatedTable = {}
for i,v in ipairs(DescQuery) do
local Class = v.ClassName
local ValidProps = Instances[Class]
local ReplicatedProps = {ClassName = Class} -- add a way to get the real parent path, i am lazy so i did not add it
--ReplicatedProps.Parent =
--print(Class,ValidProps)
for _,PropInfo in ValidProps do
-- check if the property is a default value instead of a custom value
-- if it is custom, add it to the list of properties to replicate
local Val = v[PropInfo.Name]
if Val == PropInfo.Default then continue end
ReplicatedProps[PropInfo.Name] = Val
end
table.insert(ReplicatedTable,ReplicatedProps)
end
-- compress replicatedtable into json format, then into a buffer, then compress the buffer and send it
ReplicatedTable = buffer.fromstring(game:GetService("HttpService"):JSONEncode(ReplicatedTable))
ReplicatedTable = ES:CompressBuffer(ReplicatedTable,Enum.CompressionAlgorithm.Zstd,5)
MS:PublishAsync("Topic name here",ReplicatedTable)
-- decompress the buffer and reconstruct the instance on a new server
MS:SubscribeAsync("Topic name here",function(Buffer: buffer)
local InstanceData = ES:DecompressBuffer(Buffer,Enum.CompressionAlgorithm.Zstd) -- string buffer
InstanceData = game:GetService("HttpService"):JSONDecode(buffer.readstring(InstanceData,0,buffer.len(InstanceData)))
-- reconstruct instance here
for i,InstanceData in ipairs(InstanceData) do
local Inst = Instance.new(InstanceData.ClassName)
local Parent = InstanceData.Parent -- is a string
InstanceData.Parent = nil
InstanceData.ClassName = nil
for Prop,Val in InstanceData do
Inst[Prop] = Val
end
-- add method to set parent here
end
end)
it may also be possible to do this with memorystoreservice, which offers better get/set limits but this is the first thing i thought of
TeleportService only manages connecting players to new server instances, it doesn’t actually serialize their avatar or anything like that. It just boots you out of one server and logs you into another. You will probably need to use one of: DataStoreService, MemoryStoreService, or MessagingService.
You would use DataStores or MemoryStores if you want to capture player-specific state that has to move with the player (i.e. be cleaned up on the server they’re leaving and get reconstructed on the next server they join), just like any other player save data.
MessagingService would make more sense if you need to serialize some gamestate and transfer it between two already-running server instances. Like if your train leaves the area represented by one server and has to appear on another server, completely unrelated to players leaving/joining, then MessagingService is a way to do this. When you despawn the train on the server it’s leaving, you’d message other servers with the names of the places the train is leaving and entering, and any matching servers (could be one or more) would respond by spawning the train where it ought to be if it were coming from the previous region.
MessagingService is fine for a quick handoff, but it’s not reliable for long-term state if the destination server isn’t already running or if there’s a network hiccup. If that train needs to persist through a server crash or a restart, you really should be using MemoryStoreService with a TTL. It handles the data much better than just firing a message into the void and hoping a specific server picks it up in time.
I understand what did you say. The technology of “teleporting” is:
- When train approaches the border of the place, read the randomly generated ID of the train, velocity, pantographs state, engine state etc.
- Remove the train
- Teleport the player (with TeleportService")
- Transfer data to other place (using TeleportOptions I guess?)
- On other place, player is teleported here, somewhere that it’s not visible
- Read the data given from previous place to spawn a train by the ID, with data like velocity, pantographs state, engine state etc.
- Teleport the player into the train assigned by the train ID
However, how to implement this?
you can use MessageService to teleport instances to other places in the same experience, so if you are doing that, I recommend you convert the instance into a table with all its properties & rebuild it in another place.
you can use ReflectionService to get the properties btw
What about buffers? They are more compact than tables
And how to transfer properties? With TeleportOptions?
I discovered one problem while using MessagingService: PublishAsync is triggered on absolutely every server of the same experience. There’s a video:
Just going off what you’re asking about MessagingService, you’re looking for some type of data transfer with the teleporting player, I take it? Possibly, you could try Teleport Options, specifically SetTeleportData.
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions:SetTeleportData({toSeatID = ADestinationSeat})
TeleportService:TeleportAsync(destinationPlaceId, {player}, teleportOptions)
Players.PlayerAdded:Connect(function(player)
local data = player:GetJoinData().TeleportData
if data == nil then return end
-- data.toSeatID is the seat to move and seat them to
end)
Going to have to be pretty tricky about this.. Maybe a Train Station to different place Train Station would be smoother.
that is what messaging service does, if you need to specify a jobid then add a jobid string into the table so each server can check if that server is the one it should replicate on or change the message subject to add the jobid after the generic name (Replicatorg34g323m-4373v3-hg34dd etc) so the firing server only sends the message to that single server
this should have been stated in my original post, but for your use case you simply need to attach something to the player’s data to specify the train cab names to replicate and at what position so the next server can clone, position, and parent the cabs. i don’t read posts completely so sometimes i get ahead of myself but that would be the best option for you. you should also do checks to make sure the arriving server is correct so you don’t randomly clone a train in the “starter” server
Well you don’t need to send serialized parts over to the other place, you can only send a minimal message with info that actually matters, like train location info and configs. The other server can have a copy of the default train and alter it properly to match that message config so it is seamless / identical to the other server train. The only situation in which you should consider serializing parts is if the player can directly edit the train part by part for all parts which is extremely unlikely, and even there they can likely only edit the parts in specific ways, so even in that scenario you can compress a lot.
Now to send the message over there are many ways to do so, two that come to mind are through teleport data and through memory stores (No reason to store said data in datastores since it isn’t permanent but only stored temporarily for the transition between places). I am not certain if messaging service is a good option for this, because by definition it broadcasts messages to other servers, and you can’t be certain that the other server will be ready to pick it up by the time it is broadcasted (or that you wont wait for too long and cause delays on the other side, etc).
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.