mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 14:01:37 +00:00
Implement live syncback service properties encoding and enhance syncback functionality
- Introduced a new `encodeService` helper in the plugin to serialize service properties, attributes, tags, and references alongside children data. - Updated the `performSyncback` function to utilize the new encoding method, ensuring all services are processed without child-only restrictions. - Extended the `ServiceChunk` struct to include fields for properties, attributes, tags, and references, improving data handling during syncback. - Modified the `build_dom_from_chunks` function to apply service properties and resolve references when reconstructing the service instances. - Added comprehensive tests to validate the new service properties handling, ensuring accurate synchronization and data integrity. These enhancements significantly improve the live syncback process, allowing for better service data management and consistency.
This commit is contained in:
parent
30e032b27e
commit
72ad84b5a7
16 changed files with 896 additions and 444 deletions
|
|
@ -1,6 +1,5 @@
|
|||
local ChangeHistoryService = game:GetService("ChangeHistoryService")
|
||||
local Players = game:GetService("Players")
|
||||
local SerializationService = game:GetService("SerializationService")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
local RunService = game:GetService("RunService")
|
||||
|
||||
|
|
@ -47,6 +46,8 @@ local Theme = require(script.Theme)
|
|||
|
||||
local Http = require(Packages.Http)
|
||||
|
||||
local encodeService = require(Plugin.ChangeBatcher.encodeService)
|
||||
|
||||
local Page = require(script.Page)
|
||||
local Notifications = require(script.Components.Notifications)
|
||||
local TextButton = require(script.Components.TextButton)
|
||||
|
|
@ -641,12 +642,8 @@ function App:performSyncback()
|
|||
local services = {}
|
||||
for _, className in SYNCBACK_SERVICES do
|
||||
local ok, service = pcall(game.FindService, game, className)
|
||||
if ok and service and #service:GetChildren() > 0 then
|
||||
local buf = SerializationService:SerializeInstancesAsync(service:GetChildren())
|
||||
table.insert(services, {
|
||||
className = className,
|
||||
data = buf,
|
||||
})
|
||||
if ok and service then
|
||||
table.insert(services, encodeService(service))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
101
plugin/src/ChangeBatcher/encodeService.lua
Normal file
101
plugin/src/ChangeBatcher/encodeService.lua
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
local SerializationService = game:GetService("SerializationService")
|
||||
|
||||
local Packages = script.Parent.Parent.Parent.Packages
|
||||
local Log = require(Packages.Log)
|
||||
local RbxDom = require(Packages.RbxDom)
|
||||
|
||||
local encodeProperty = require(script.Parent.encodeProperty)
|
||||
local UNENCODABLE_DATA_TYPES = require(script.Parent.propertyFilter)
|
||||
|
||||
local SKIP_PROPERTIES = {
|
||||
Parent = true,
|
||||
Name = true,
|
||||
Archivable = true,
|
||||
}
|
||||
|
||||
return function(service: Instance)
|
||||
local properties = {}
|
||||
local attributes = {}
|
||||
local tags = {}
|
||||
local refs = {}
|
||||
|
||||
local classDescriptor = RbxDom.findClassDescriptor(service.ClassName)
|
||||
if classDescriptor then
|
||||
for propertyName, propertyMeta in pairs(classDescriptor.properties) do
|
||||
if SKIP_PROPERTIES[propertyName] then
|
||||
continue
|
||||
end
|
||||
if propertyName == "Attributes" or propertyName == "Tags" then
|
||||
continue
|
||||
end
|
||||
|
||||
local isReadable = propertyMeta.scriptability == "ReadWrite" or propertyMeta.scriptability == "Read"
|
||||
local doesSerialize = propertyMeta.serialization ~= "DoesNotSerialize"
|
||||
|
||||
if isReadable and doesSerialize then
|
||||
local descriptor = RbxDom.findCanonicalPropertyDescriptor(service.ClassName, propertyName)
|
||||
if descriptor then
|
||||
if UNENCODABLE_DATA_TYPES[descriptor.dataType] then
|
||||
continue
|
||||
end
|
||||
|
||||
if descriptor.dataType == "Ref" then
|
||||
local readOk, target = descriptor:read(service)
|
||||
if readOk and target and target.Parent == service then
|
||||
refs[propertyName] = {
|
||||
name = target.Name,
|
||||
className = target.ClassName,
|
||||
}
|
||||
end
|
||||
continue
|
||||
end
|
||||
|
||||
local encodeOk, encoded = encodeProperty(service, propertyName, descriptor)
|
||||
if encodeOk and encoded ~= nil then
|
||||
properties[propertyName] = encoded
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local attrOk, attrMap = pcall(function()
|
||||
return service:GetAttributes()
|
||||
end)
|
||||
if attrOk and attrMap and next(attrMap) then
|
||||
local descriptor = RbxDom.findCanonicalPropertyDescriptor(service.ClassName, "Attributes")
|
||||
if descriptor then
|
||||
local encodeOk, encoded = encodeProperty(service, "Attributes", descriptor)
|
||||
if encodeOk and encoded ~= nil then
|
||||
attributes = encoded
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tagOk, tagList = pcall(function()
|
||||
return service:GetTags()
|
||||
end)
|
||||
if tagOk and tagList and #tagList > 0 then
|
||||
tags = tagList
|
||||
end
|
||||
|
||||
local children = service:GetChildren()
|
||||
local data = buffer.create(0)
|
||||
if #children > 0 then
|
||||
local serializeOk, result = pcall(SerializationService.SerializeInstancesAsync, SerializationService, children)
|
||||
if serializeOk then
|
||||
data = result
|
||||
else
|
||||
Log.warn("Failed to serialize children of {}: {}", service.ClassName, tostring(result))
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
className = service.ClassName,
|
||||
data = data,
|
||||
properties = properties,
|
||||
attributes = attributes,
|
||||
tags = tags,
|
||||
refs = refs,
|
||||
}
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue