Commit Graph

432 Commits

Author SHA1 Message Date
boatbomber
85655ca84f Heuristic hydration matching instead of hard dependency on GetChildren ordering (#1266)
### Summary

When two or more sibling instances share the same `Name` and
`ClassName`, Rojo's reconciler previously paired them with their
server-side counterparts purely by child order (first-unvisited match in
`GetChildren()` order). If the workspace child order ever diverged from
the server's, the wrong instance got paired so each duplicate could
inherit a sibling's properties.

This is the root of the #1257 bug: the welded parts would oscillate
between positions on each connect/disconnect because hydration kept
mis-pairing them. (#1265 stopped the sync fallback from scrambling child
order in the first place but this PR makes hydration robust even when
order *does* diverge.)

This PR makes `hydrate` break ties by comparing properties: when several
existing children match on `Name`+`ClassName`, it scores each candidate
by how many of the virtual instance's properties match the candidate's
live values, and picks the best. Order remains the tiebreak when scores
are equal, so behavior is unchanged for uniquely-named instances and for
indistinguishable siblings.

### Changes

- `trueEquals.lua`: extracted verbatim from `diff.lua` (the fuzzy
value-equality helper) so it can be shared. No behavior change;
`diff.lua` now requires it.
- `countMatchingProperties.lua`: added
`countMatchingProperties(instance, virtualInstance, instanceMap) ->
number`. Skips `Ref` properties (the instanceMap isn't fully built
mid-hydrate, so refs can't be decoded reliably, and they're a poor
disambiguator anyway) and any property that can't be read or decoded.
- `hydrate.lua`: See details below.

### Hydrate Changes

This touches `hydrate`, which runs over the whole tree on every
connect/resync, so I want state clearly that **the common path is faster
than before, not slower** even for parents with thousands of children!

The old algorithm was a nested scan: for each of `V` virtual children,
scan existing children until the first unvisited `Name`+`ClassName`
match. Two costs stand out:
- A `pcall` (to guard DataModel permission errors) ran on every
comparison (up to `V*E` `pcall`s per parent).
- Even for in-order trees the re-scanning of the visited prefix made it
`O(V^2)`.

The new algorithm does a single bucketing pass, then `O(1)` lookups:
1. One `O(E)` pass groups existing children into nested
`buckets[name][className]` tables. This runs exactly `E` `pcall`s total
(one per child), down from the `V*E` worst case.
2. Each virtual child does an `O(1)` bucket lookup to find its
candidates.
3. A per-bucket cursor skips already-paired children, so order-based
matching is amortized `O(1)` per child instead of rescanning.

| Scenario | Old | New |
| ------------------------------------------------ |
--------------------------------------- |
--------------------------------------------- |
| Unique-named children (typical, incl. thousands) | `O(V^2)`, plus up
to `V*E` pcalls | `O(V + E)`, plus exactly `E` pcalls |
| `C <= 32` candidates | `O(C^2)` | `O(P * C^2)` scoring |
| `C > 32` candidates | `O(C^2)` | `O(C)` |

Property scoring (`getProperty`/`decodeValue`/`trueEquals`) is the only
new expense, and it's gated two ways:
- It runs only when a `Name`+`ClassName` group has >=2 candidates (i.e.
never for uniquely-named instances).
- A cap, `MAX_CANDIDATES_TO_SCORE = 32`, means scoring only kicks in
once a group has <=32 unvisited candidates. A folder of thousands of
identically-named parts therefore does not trigger scoring; it falls
back to the original order-based pairing. The worst-case added scoring
work is bounded to roughly `32^2` property comparisons per group,
independent of group size.

So overall this is faster when you have unique names or many children.
It is slower but more robust when you have small groups of duplicate
names. Memory usage is increased as it creates the candidate buckets.
2026-06-01 17:29:22 -07:00
boatbomber
ae8735c80a Fix replaceInstances messing up GetChildren ordering (#1265)
Fixes #1257. replaceInstances now preserves GetChildren ordering.

I also had the unit tests unreliably say that Packages wasn't a member
of ReplicatedStorage so I added WaitForChild and tests run 100% for me
now.
2026-06-01 17:04:25 -07:00
Ken Loeffler
988efb45b1 Use lossy conversion for msgpack UInt64 decode in plugin (#1255) 2026-05-29 10:45:08 -07:00
Micah
9bbb1edd79 Upload plugin as part of release workflow (#1227) 2026-02-14 11:10:36 -08:00
Micah
4deda0e155 Use msgpack for API (#1176) 2026-02-12 18:37:24 -08:00
boatbomber
4965165ad5 Add option to forget prior info for place in reminder notif (#1215) 2026-01-23 21:15:34 +00:00
boatbomber
68eab3479a Fix notification unmount thread cancel bug (#1211) 2026-01-19 16:35:19 -08:00
Ken Loeffler
02b41133f8 Use post for ref patch and serialize (#1192) 2026-01-19 22:44:42 +00:00
Micah
42568b9709 Release Rojo v7.7.0-rc.1 (#1174) 2025-11-27 12:10:57 -08:00
boatbomber
87f58e0a55 Use WebSocket instead of Long Polling (#1142) 2025-11-26 19:57:01 -08:00
Ken Loeffler
015b5bda14 Set crate and plugin versions to 7.7.0-prealpha (#1170) 2025-11-21 07:02:09 -08:00
boatbomber
071b6e7e23 Improved string diff viewer (#994) 2025-11-18 20:26:44 -08:00
quaywinn
31ec216a95 Remove pairs() and ipairs() (#1150) 2025-11-18 18:49:52 -08:00
quaywinn
03410ced6d Use buffer for ClassIcon EditableImages (#1149) 2025-11-07 13:07:19 -08:00
Micah
825726c883 Release 7.6.1 (#1151) 2025-11-06 18:49:05 -08:00
boatbomber
54e63d88d4 Slightly improve initial sync hangs (#1140) 2025-11-06 00:06:42 -08:00
boatbomber
181cc37744 Improve sync fallback robustness (#1135) 2025-10-20 20:13:47 -07:00
boatbomber
cd78f5c02c Fix postcommit callbacks being skipped (#1132) 2025-10-14 12:13:59 -07:00
Micah
441c469966 Release Rojo v7.6.0 (#1125) 2025-10-10 19:17:55 -07:00
Micah
80a381dbb1 Use SerializationService as a fallback for when patch application fails (#1030) 2025-09-21 15:09:20 -07:00
boatbomber
54e0ff230b Improvements to sync reminder UX (#1096) 2025-08-28 17:15:34 -07:00
wad
4e9e6233ff fix: apply gameId and placeId only after initial sync (#1104) 2025-08-15 18:12:36 -07:00
Sebastian Stachowicz
3002d250a1 Fix Table diff colors (#1084) 2025-07-31 19:36:03 -07:00
Sebastian Stachowicz
7f68d9887b Fixed nil -> nil props showing up as failing in patch visualizer (plugin) (#1081) 2025-07-25 15:27:11 -07:00
morosanu
7860f2717f Fix auto connect for play mode (#1066) 2025-07-22 15:12:16 -07:00
boatbomber
60f19df9a0 Show update indicator on version header (#1069) 2025-06-21 02:53:45 +00:00
boatbomber
951f0cda0b Show the plugin version on the Error page (#1068) 2025-06-20 18:28:04 -07:00
Micah
b2c4f550ee Release v7.5.1 (#1035) 2025-04-25 13:56:01 -07:00
Ken Loeffler
d935115591 Release 7.5.0 (#1033) 2025-04-25 19:46:16 +01:00
Cameron Campbell
bd2ea42732 Fixes issues with refs in the plugin. (#1005) 2025-04-18 08:44:11 -07:00
Micah
a7a4f6d8f2 Update rbx-dom-lua database to latest version (#1029) 2025-04-13 07:42:41 -07:00
Parritz
7dee898400 Add place ID blacklist config (#1021) 2025-04-03 08:37:40 -07:00
Micah
833320de64 Update rbx-dom (#1023) 2025-04-02 11:32:27 -07:00
boatbomber
0d6ff8ef8a Improve notification layout (#997) 2025-01-13 16:06:49 -08:00
boatbomber
19ca2b12fc Add locked tooltip (#998)
Adds the ability to define descriptive tooltips for settings when they
are locked.


![image](https://github.com/user-attachments/assets/5d5778c8-911b-4358-b4e6-f0389270ad76)


Makes some minor improvements to tooltip layout logic as well.
2024-12-28 15:03:11 -08:00
boatbomber
b7d3394464 Plugin dev ux improvements (#992)
Co-authored-by: kennethloeffler <kenloef@gmail.com>
2024-11-10 15:53:58 -08:00
boatbomber
8c33100d7a Use FontFace and consistent text sizing (#988) 2024-11-09 12:05:57 +00:00
Kenneth Loeffler
bc2c76e5e2 Use 7.5.0-prealpha for master branch version, not 7.4.4
<p dir="auto">in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="2636858743" data-permission-text="Title is private" data-url="https://github.com/rojo-rbx/rojo/issues/989" data-hovercard-type="pull_request" data-hovercard-url="/rojo-rbx/rojo/pull/989/hovercard" href="https://github.com/rojo-rbx/rojo/pull/989">#989</a>, we changed Rojo's version number on the master branch to 7.4.4. This is a little odd, because 7.4.4 is already released, is diverged from the master branch, and we are not working towards 7.4.4 on the master branch. If we're going to spend time on this, I think we should use a more appropriate version number.</p>
<p dir="auto">This PR changes the version number to 7.5.0-prealpha, since Rojo's master branch is currently undergoing development towards 7.5.0. We will most likely <strong>not</strong> be making a release of this version - the only intent is better clarity for those running Rojo's latest master.</p>
2024-11-06 15:59:03 +00:00
boatbomber
4a7bddbc09 Update version in master branch (#989) 2024-11-05 18:10:24 -08:00
boatbomber
e316fdbaef Make sync reminder more detailed (#987) 2024-11-05 22:47:07 +00:00
Kenneth Loeffler
73097075d4 Update rbx-dom dependencies (#965) 2024-08-22 20:03:06 +01:00
boatbomber
4b5db4e5a9 Check for compatible updates in plugin (#832) 2024-08-05 11:34:29 -07:00
boatbomber
62f4a1f3c2 Use history recording and don't do anything permanent (#915) 2024-05-30 12:28:58 -07:00
boatbomber
3d4e387d35 Redesign settings UI in plugin (#886) 2024-05-13 10:36:03 -07:00
Micah
2c46640105 Allow openScriptsExternally option to be changed during sync (#911) 2024-05-08 12:34:00 -07:00
boatbomber
b2f133e6f1 Patch visualizer redesign (#883) 2024-04-02 00:04:58 -07:00
Barış
c7a4f892e3 Add never option to Confirmation (#893) 2024-03-14 19:41:21 +00:00
EgoMoose
8f9e307930 Trim plugin version string (#890)
Duplicate of https://github.com/rojo-rbx/rojo/pull/889, but based on
master as per request.

This PR is a very small change that fixes the string pattern that reads
the rojo version from `Version.txt`. Currently this reads an extra
new-line character which makes reading the version text in the plugin
difficult.

It seems the rust side of things already trims the string when
comparing, but the lua side does not.
2024-03-13 09:50:41 -07:00
boatbomber
26181a5a1f Use GuiState instead of manual calculation for tooltips (#884) 2024-02-29 14:50:06 -08:00
boatbomber
edf87bf9a3 Build tree ancestry correctly (#882) 2024-02-29 14:27:46 -08:00