Basically, I want to be able to make a part on my client and replicate that data to the server. And yes, the part will originate on the client. Also not just NetworkOwnership
, but every property will replicate to the server. And if there is a way at all, please don’t just say it’s unsafe to use and not tell me. I’m just curious if this is possible. (preferably without RemoteEvents
)
I’m pretty sure that without remotes this is kind of impossible, do you still want a response with the use of remote events or nah?
If it’s impossible to do it without remotes then I guess I could use them, so sure
No, you cannot replicate a client-created part to the server conventionally. This is what filtering enabled prevents!
I’m not simply looking for a setting to toggle such as FilteringEnabled to grant the client access to replicate parts to the server as they wish. I’m looking for a way to send the part’s data to the server and replicate it with the server’s permission
You cannot toggle FilteringEnabled. If you wish to send the data to the server, then wrap the properties in a table and send it through a remote event/function as the instance itself cannot be sent through.
I already know FilteringEnabled is not an option. I get what you’re saying but would such a system put an unnecessary strain on the server?
It is possible, yes, with a remote function that continously sends a table of properties for the server to handle and set, however, I truly don’t know the reason you would want to do that as it’s as unsafe as it can get. It can also be preferably sped up with the new parallel luau methods.
It would be less costly than having a part replicated over the network if you reduce the number of properties you send over, unless you do it like, a hundred times a second.
More information on what you are doing can let us give you more help.
Even tho I don’t really get why someone would do this, you might have something in mind or just playing around.
⚠ WARNING ⚠
DO NOT USE IN YOUR GAME, VERY VULNERABLE
Client:
local Controller = {} do
Controller.Parts = {}
local Event = game:GetService("ReplicatedStorage").YourEvent
function ReduceTableContent(NewTable, OldTable)
local ReducedTable = {}
for key, value in pairs(NewTable) do
if OldTable[key] ~= value then
ReducedTable[key] = value
end
end
return ReducedTable
end
function Controller.IntializeReplication(Part: BasePart)
if not Controller.Parts[Part] then
Controller.Parts[Part] = {
["LastReplicatedData"] = {},
["Id"] = game.HttpService:GenerateGUID(false)
}
end
end
function Controller.Replicate(Part)
if not Part:GetAttribute("ServerPart", true) then
if Controller.Parts[Part] then
local Data = {
["Parent"] = Part.Parent,
["CFrame"] = Part.CFrame,
["Size"] = Part.Size,
["Anchored"] = Part.Anchored,
["CanCollide"] = Part.CanCollide,
["Transparency"] = Part.Transparency,
["Color"] = Part.Color
}
if Data ~= Controller.Parts[Part]["LastReplicatedData"] then
Event:FireServer({
["Id"] = Controller.Parts[Part].Id,
["Properties"] = ReduceTableContent(Data, Controller.Parts[Part].LastReplicatedData)
})
Controller.Parts[Part]["LastReplicatedData"] = Data
end
else
Controller.IntializeReplication(Part)
Controller.Replicate(Part)
end
end
end
function Controller.Init()
workspace.Replicatable.ChildAdded:Connect(function(Part: BasePart)
Controller.Replicate(Part)
end)
for i = 1,10 do
local part = Instance.new("Part") part.Name = "part"..i
part.Anchored = true
part.Position = Vector3.new(0, i, 0)
part.Parent = workspace.Replicatable
part.CollisionGroup = "replicatableparts"
end
for Index, Value in Controller.Parts do
Index.Changed:Connect(function()
Controller.Replicate(Index)
end)
end
while task.wait() do
for Index, Value in workspace:GetDescendants() do
if Value:GetAttribute("ServerPart", true) and not Value:GetAttribute("HasBeenConfigured", true) then
Value.Transparency = 1
Value.CanCollide = false
Value.Locked = true
Value.Name = Value.name.."_SERVERPART"
Value:SetAttribute("HasBeenConfigured", true)
end
end
end
end
end
return Controller
Server:
local Controller = {} do
Controller.Parts = {}
local Event = game:GetService("ReplicatedStorage").YourEvent
local InstanceNew = Instance.new
function Controller.Replicate(Player, Info: {Id: number, Properties: table})
local Part
if not Controller.Parts[Info.Id] then
Part = InstanceNew("Part")
Controller.Parts[Info.Id] = Part
else
Part = Controller.Parts[Info.Id]
end
for Property, Value in pairs(Info.Properties) do
if Part[Property] ~= Value then
Part[Property] = Value
end
end
Part:SetAttribute("ServerPart", true)
Part.CollisionGroup = "ReplicatedParts"
end
function Controller.Init()
Event.OnServerEvent:Connect(Controller.Replicate)
end
end
return Controller
Note:
I made this for fun, I don’t have time to improve it, yet it gives more than a basic idea on how this can be done BUT AGAIN DONT USE IT! Also these scripts are modules so you need to require them to use them. If you don’t know how modules work, here is the doc page for them! Also even tho “GenerateGUID” is not the best thing to use (as far as I know) I used it to save time and because it doesn’t make such a difference as this is just an example and it wont be used anywhere. I fixed the lag issue and also it is suggested to use collision groups for the replicated and replicatable parts so issues are reduced, it is not suggested to drag move a part, and it is not suggested to unanchor them, it get messy!
Fixing lag issue (I’m brainless) and also adding something to make it more smooth in a sec
Alright lag is fixed now and they are also less buggy now because of disabled collisions!
If you want to replicate property changes efficiently, use delta compression – sending properties only when they have changed. @Iampros33’s example uses this.
However, a large amount of data will be used to send over the string keys, and you would also be using an unnecessary amount of data to send certain properties, such as Transparency (Transparency is between 0 to 1, and by default would take 9 bytes because all numbers are 64-bit floats, but you can use only 1 to represent it with 2 digits of precision) and boolean properties (only 1 bit is necessary but Roblox uses 2 bytes by default). I would highly recommend using the following:
Very well said, also it could be made so instead of firing an enormous amount of events when for example its position is changed, limit it and only fire for example every .5 second (this is just an example you can use whatever works best for you) or something. It might be less smooth but it is much more optimized.
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.