-
Notifications
You must be signed in to change notification settings - Fork 181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Update reconciler / reify to use CreateMeshPartAsync to create mesh parts #534
Conversation
} | ||
|
||
for propertyName in pairs(properties) do | ||
if propertyName == "Name" then | ||
update.changedName = instance.Name | ||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change, whilst structural (it now encodes the Name field as well as setting the changedName property) has not changed the intended logic and is more concise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR looks good, thanks for the submission!
Can you back out the change to database.json
? We should be able to land any updates to rbx_dom_lua in a separate PR and it is a frequent source of merge conflicts.
I mentioned in the review comments, but I think we should remove requiresRecreate
from the patch type and instead calculate it during applyPatch
. The Rojo server produces most of the patches that the plugin receives and doesn't have any knowledge of what would require an instance to be recreated. It's bets if we let the plugin decide for itself when it goes to apply a change.
-- Custom logic for MeshParts | ||
-- see: https://github.com/rojo-rbx/rojo/issues/402 | ||
if className == "MeshPart" then | ||
local okMeshId, meshId = decodeValue(properties.MeshId, instanceMap) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to handle okMeshId
, because the second return value will not be a mesh ID if this failed to decode.
@@ -25,6 +25,7 @@ local ApiInstanceUpdate = t.interface({ | |||
id = RbxId, | |||
changedName = t.optional(t.string), | |||
changedClassName = t.optional(t.string), | |||
requiresRecreate = t.optional(t.boolean), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should update this interface at all. The server generates most of the patches that the Rojo plugin handles and it does not populate requiresRecreate
. We can calculate this when we go to apply a patch instead.
-- If the instance's className changed, or there is custom recreate logic, | ||
-- we have a bumpy ride ahead while we recreate this instance and move all | ||
-- of its children into the new version atomically...ish. | ||
if update.requiresRecreate then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are comments in this block of code about its caveats, notably not preserving existing properties if we end up needing to recreate an instance. It's probably not the end of the world, but some of the comments I left about this mostly occurring during Folder<->ModuleScript transitions are probably not accurate anymore.
it("should recreate instance in the update when the instance's ClassName changes", function() | ||
local part = Instance.new("Part") | ||
local properties = { | ||
ClassName = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should set this value to a real ClassName
so that future validation in the patch update function won't choke when it sees a bool instead.
@@ -156,7 +158,33 @@ return function() | |||
expect(value.Value).to.equal("WORLD") | |||
end) | |||
|
|||
it("should recreate instances when changedClassName is set, preserving children", function() | |||
it("should recreate instances for MeshId updates", function() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great test!
-- If the instance's className changed, or there is custom recreate logic, | ||
-- we have a bumpy ride ahead while we recreate this instance and move all | ||
-- of its children into the new version atomically...ish. | ||
if update.requiresRecreate then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having requiresRecreate
as a property here, we should check the conditions that would cause us to recreate an instance directly. For now, that's just changedClassName ~= nil or changedProperties["MeshId"] ~= nil
.
|
||
-- It is okay to provide default properties here, because | ||
-- they will be overriden on the update cycle | ||
return InsertService:CreateMeshPartAsync(meshId, Enum.CollisionFidelity.Default, Enum.RenderFidelity.Automatic) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the first time we'll be introducing an async function into Rojo's reconciler bits. This is a possible source of bugs that we should watch out for in the future.
-- It is okay to provide default properties here, because | ||
-- they will be overriden on the update cycle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-- It is okay to provide default properties here, because | |
-- they will be overriden on the update cycle | |
-- It is okay to provide default properties here, because | |
-- they will be set when properties are applied in reify. |
50d350c
to
6c1beb9
Compare
Hm. Why was this closed? |
It was closed in favour of #786. |
Closes #402.
Problem
Currently, Rojo does not support creation of some instances and properties via the Studio plugin - notably UnionOperations and MeshParts. MeshParts can in fact be created by Plugins through the InsertService.CreateMeshPartAsync method at Plugin security.
This impacts developers using Rojo to work, as it prevents them from live importing any such instances (and can only be created from a file via
rojo build
or manual import).Solution
This pull request exclusively modifies the Lua plugin; no changes were necessary to the Rojo binary itself. The changes have a soft dependency on a pull request to rbx-dom to update the database files, although this is not a requirement.
The primary change was to modify the reify function to include a switch for custom instance creation logic which could be expanded in the future if necessary.
This change was coupled closely with the implementation of the
requiresRecreate
property ofApiInstanceUpdate
objects, which is a partial replacement for thechangedClassName
property. This property triggers a condition in the applyPatch function to recreate the instance using reify if therequiresRecreate
property is present (previously done for thechangedClassName
property).The
requiresRecreate
property is set during the creation of an update patch (either in batch, in encodePatchUpdate, or during diff).Tests
Tests have been implemented which support the new feature being added. A dedicated test project (
test-projects/mesh_parts/default.project.json
) has been included with two MeshParts (onerbxm
and onerbxmx
), of the Utah Teapot.Other
The development version of Rojo was bumped to
7.0.0 (latest)
.