diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 58eb4182..69a24916 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -6,6 +6,12 @@ local setCanonicalProperty = require(script.Parent.setCanonicalProperty) local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) local Types = require(script.Parent.Types) +local function setParent(instance, newParent) + pcall(function() + instance.Parent = newParent + end) +end + local Reconciler = {} Reconciler.__index = Reconciler @@ -117,7 +123,7 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) -- Some instances, like services, don't like having their Parent -- property poked, even if we're setting it to the same value. - setCanonicalProperty(instance, "Parent", parent) + setParent(instance, parent) end return instance @@ -154,7 +160,7 @@ function Reconciler:__reify(virtualInstancesById, id, parent) self:__reify(virtualInstancesById, childId, instance) end - setCanonicalProperty(instance, "Parent", parent) + setParent(instance, parent) self.instanceMap:insert(id, instance) return instance diff --git a/plugin/src/rojoValueToRobloxValue.lua b/plugin/src/rojoValueToRobloxValue.lua index b5855b2a..94c57664 100644 --- a/plugin/src/rojoValueToRobloxValue.lua +++ b/plugin/src/rojoValueToRobloxValue.lua @@ -1,38 +1,33 @@ -local primitiveTypes = { - Bool = true, - Enum = true, - Float32 = true, - Float64 = true, - Int32 = true, - Int64 = true, - String = true, -} - -local directConstructors = { - CFrame = CFrame.new, - Color3 = Color3.new, - Color3uint8 = Color3.fromRGB, - Rect = Rect.new, - UDim = UDim.new, - UDim2 = UDim2.new, - Vector2 = Vector2.new, - Vector2int16 = Vector2int16.new, - Vector3 = Vector3.new, - Vector3int16 = Vector3int16.new, -} +local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom) local function rojoValueToRobloxValue(value) - if primitiveTypes[value.Type] then - return value.Value + -- TODO: Manually decode this value by looking up its GUID The Rojo server + -- doesn't give us valid ref values yet, so this isn't important yet. + if value.Type == "Ref" then + return nil end - local constructor = directConstructors[value.Type] - if constructor ~= nil then - return constructor(unpack(value.Value)) + -- TODO: Remove this once rbx_dom_weak and rbx_dom_lua agree on encoding + if value.Type == "BinaryString" then + local actualValue = "" + + for i = 1, #value.Value do + actualValue = actualValue .. string.char(i) + end + + value = { + Type = "BinaryString", + Value = actualValue, + } end - local errorMessage = ("The Rojo plugin doesn't know how to handle values of type %q yet!"):format(tostring(value.Type)) - error(errorMessage) + local success, decodedValue = RbxDom.EncodedValue.decode(value) + + if not success then + error(decodedValue, 2) + end + + return decodedValue end return rojoValueToRobloxValue \ No newline at end of file diff --git a/plugin/src/setCanonicalProperty.lua b/plugin/src/setCanonicalProperty.lua index 6e5eacd6..fabbd733 100644 --- a/plugin/src/setCanonicalProperty.lua +++ b/plugin/src/setCanonicalProperty.lua @@ -1,33 +1,17 @@ +local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom) + local Logging = require(script.Parent.Logging) --[[ Attempts to set a property on the given instance. - - This method deals in terms of what Rojo calls 'canonical properties', which - don't necessarily exist either in serialization or in Lua-reflected APIs, - but may be present in the API dump. - - Ideally, canonical properties map 1:1 with properties we can assign, but in - some cases like LocalizationTable contents and CollectionService tags, we - have to read/write properties a little differently. ]] local function setCanonicalProperty(instance, key, value) - -- The 'Contents' property of LocalizationTable isn't directly exposed, but - -- has corresponding (deprecated) getters and setters. - if instance.ClassName == "LocalizationTable" and key == "Contents" then - instance:SetContents(value) - return - end - - -- Temporary workaround for fixing issue #141 in this specific case. - if instance.ClassName == "Lighting" and key == "Technology" then - return + if not RbxDom.CanonicalProperty.isScriptable(instance.ClassName, key) then + return false end -- If we don't have permissions to access this value at all, we can skip it. - local readSuccess, existingValue = pcall(function() - return instance[key] - end) + local readSuccess, existingValue = RbxDom.CanonicalProperty.read(instance, key) if not readSuccess then -- An error will be thrown if there was a permission issue or if the @@ -35,17 +19,13 @@ local function setCanonicalProperty(instance, key, value) -- because it's probably their fault. if existingValue:find("lacking permission") then Logging.trace("Permission error reading property %s on class %s", tostring(key), instance.ClassName) - return + return false else error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, existingValue), 2) end end - local writeSuccess, err = pcall(function() - if existingValue ~= value then - instance[key] = value - end - end) + local writeSuccess, err = RbxDom.CanonicalProperty.write(instance, key, value) if not writeSuccess then error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2)