mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 14:01:37 +00:00
Enhance scripts-only mode handling and improve temp ID resolution
- Introduced a new mechanism in ServeSession to manage scripts-only mode, ensuring proper handling of temporary IDs during script additions. - Updated the applyPatch function to remap only scripts-only temp IDs, preventing false positives with legitimate additions. - Modified the API to resolve intermediate container temp IDs to real tree references, enhancing the integrity of parent-child relationships for new scripts. - Added tests to verify the functionality of scripts-only mode and the resolution of temp IDs. These changes aim to optimize script management and improve the overall functionality of the session handling.
This commit is contained in:
parent
dcd48642be
commit
57433a0158
26 changed files with 274 additions and 63 deletions
|
|
@ -35,6 +35,10 @@ function InstanceMap.new(onInstanceChanged)
|
|||
-- Callback invoked when a new instance is inserted into the map.
|
||||
-- Used by ChangeBatcher to resolve pending unresolved Ref properties.
|
||||
onInstanceInserted = nil,
|
||||
|
||||
-- Temp IDs generated by DescendantAdded watchers in scripts-only mode.
|
||||
-- Used by applyPatch to distinguish echo additions from legitimate ones.
|
||||
scriptsOnlyTempIds = {},
|
||||
}
|
||||
|
||||
return setmetatable(self, InstanceMap)
|
||||
|
|
|
|||
|
|
@ -71,24 +71,29 @@ local function applyPatch(instanceMap, patch)
|
|||
-- When the plugin pre-inserts instances with temp IDs and the server
|
||||
-- broadcasts the same instances with real Refs, remap the InstanceMap
|
||||
-- entries rather than creating duplicates via reify.
|
||||
local remapProgress = true
|
||||
while remapProgress do
|
||||
remapProgress = false
|
||||
for id, virtualInstance in pairs(patch.added) do
|
||||
local parentInstance = instanceMap.fromIds[virtualInstance.Parent]
|
||||
if not parentInstance then
|
||||
continue
|
||||
end
|
||||
for _, child in parentInstance:GetChildren() do
|
||||
if child.Name == virtualInstance.Name and child.ClassName == virtualInstance.ClassName then
|
||||
local existingId = instanceMap.fromInstances[child]
|
||||
if existingId and existingId ~= id then
|
||||
Log.trace("Echo remap: {} -> {} for {}", existingId, id, child:GetFullName())
|
||||
instanceMap:removeId(existingId)
|
||||
instanceMap:insert(id, child)
|
||||
patch.added[id] = nil
|
||||
remapProgress = true
|
||||
break
|
||||
-- Only remap IDs explicitly tracked as scripts-only temp IDs to avoid
|
||||
-- false positives with legitimate same-named additions.
|
||||
if next(instanceMap.scriptsOnlyTempIds) then
|
||||
local remapProgress = true
|
||||
while remapProgress do
|
||||
remapProgress = false
|
||||
for id, virtualInstance in pairs(patch.added) do
|
||||
local parentInstance = instanceMap.fromIds[virtualInstance.Parent]
|
||||
if not parentInstance then
|
||||
continue
|
||||
end
|
||||
for _, child in parentInstance:GetChildren() do
|
||||
if child.Name == virtualInstance.Name and child.ClassName == virtualInstance.ClassName then
|
||||
local existingId = instanceMap.fromInstances[child]
|
||||
if existingId and existingId ~= id and instanceMap.scriptsOnlyTempIds[existingId] then
|
||||
Log.trace("Echo remap: {} -> {} for {}", existingId, id, child:GetFullName())
|
||||
instanceMap.scriptsOnlyTempIds[existingId] = nil
|
||||
instanceMap:removeId(existingId)
|
||||
instanceMap:insert(id, child)
|
||||
patch.added[id] = nil
|
||||
remapProgress = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -906,18 +906,39 @@ function ServeSession:__connectScriptsOnlyWatchers()
|
|||
return
|
||||
end
|
||||
|
||||
for _, instance in self.__instanceMap.fromIds do
|
||||
if instance.Parent ~= game then
|
||||
continue
|
||||
local services = {}
|
||||
if self.__serverInfo and self.__serverInfo.visibleServices then
|
||||
for _, serviceName in ipairs(self.__serverInfo.visibleServices) do
|
||||
local ok, service = pcall(game.GetService, game, serviceName)
|
||||
if ok and service then
|
||||
table.insert(services, service)
|
||||
end
|
||||
end
|
||||
else
|
||||
for _, instance in self.__instanceMap.fromIds do
|
||||
if instance.Parent == game then
|
||||
table.insert(services, instance)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local conn = instance.DescendantAdded:Connect(function(descendant)
|
||||
for _, service in services do
|
||||
local conn = service.DescendantAdded:Connect(function(descendant)
|
||||
if not self.__twoWaySync then
|
||||
return
|
||||
end
|
||||
if self.__status ~= Status.Connected then
|
||||
return
|
||||
end
|
||||
if Settings:get("oneShotSync") then
|
||||
return
|
||||
end
|
||||
if RunService:IsRunning() then
|
||||
return
|
||||
end
|
||||
if self.__changeBatcher:isPaused() then
|
||||
return
|
||||
end
|
||||
if not descendant:IsA("LuaSourceContainer") then
|
||||
return
|
||||
end
|
||||
|
|
@ -936,18 +957,26 @@ function ServeSession:__connectScriptsOnlyWatchers()
|
|||
end
|
||||
|
||||
local mappedParent = current
|
||||
if not mappedParent then
|
||||
return
|
||||
end
|
||||
local mappedParentId = self.__instanceMap.fromInstances[mappedParent]
|
||||
local mappedParentId = mappedParent and self.__instanceMap.fromInstances[mappedParent]
|
||||
|
||||
if not mappedParentId then
|
||||
return
|
||||
local rootId = self.__instanceMap.fromInstances[game]
|
||||
if not rootId then
|
||||
return
|
||||
end
|
||||
table.insert(chain, 1, service)
|
||||
mappedParentId = rootId
|
||||
end
|
||||
|
||||
local patch = PatchSet.newEmpty()
|
||||
local prevParentId = mappedParentId
|
||||
|
||||
for _, intermediate in chain do
|
||||
local existingId = self.__instanceMap.fromInstances[intermediate]
|
||||
if existingId then
|
||||
prevParentId = existingId
|
||||
continue
|
||||
end
|
||||
local tempId = string.gsub(HttpService:GenerateGUID(false), "-", ""):lower()
|
||||
patch.added[tempId] = {
|
||||
parent = prevParentId,
|
||||
|
|
@ -957,6 +986,7 @@ function ServeSession:__connectScriptsOnlyWatchers()
|
|||
children = {},
|
||||
}
|
||||
self.__instanceMap:insert(tempId, intermediate)
|
||||
self.__instanceMap.scriptsOnlyTempIds[tempId] = true
|
||||
prevParentId = tempId
|
||||
end
|
||||
|
||||
|
|
@ -969,11 +999,13 @@ function ServeSession:__connectScriptsOnlyWatchers()
|
|||
)
|
||||
for tempId in patch.added do
|
||||
self.__instanceMap:removeId(tempId)
|
||||
self.__instanceMap.scriptsOnlyTempIds[tempId] = nil
|
||||
end
|
||||
return
|
||||
end
|
||||
patch.added[scriptTempId] = encoded
|
||||
self.__instanceMap:insert(scriptTempId, descendant)
|
||||
self.__instanceMap.scriptsOnlyTempIds[scriptTempId] = true
|
||||
|
||||
Log.info(
|
||||
"Scripts-only: detected new script {} outside mapped tree, sending to server",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue