Add sync locking for Team Create (#590)

* Add sync locking

* Steal lock from users who left without releasing

* Do not remove lock as unknown instance

* Don't delete non Archivable instance
This commit is contained in:
boatbomber
2022-08-08 01:08:55 -07:00
committed by GitHub
parent 05adb82dda
commit 4cb49c7825
2 changed files with 68 additions and 0 deletions

View File

@@ -1,3 +1,6 @@
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Rojo = script:FindFirstAncestor("Rojo")
local Plugin = Rojo.Plugin
local Packages = Rojo.Packages
@@ -92,7 +95,65 @@ function App:getHostAndPort()
return host, port
end
function App:claimSyncLock()
if #Players:GetPlayers() == 0 then
Log.trace("Skipping sync lock because this isn't in Team Create")
return true
end
local lock = ServerStorage:FindFirstChild("__Rojo_SessionLock")
if not lock then
lock = Instance.new("ObjectValue")
lock.Name = "__Rojo_SessionLock"
lock.Archivable = false
lock.Value = Players.LocalPlayer
lock.Parent = ServerStorage
Log.trace("Created and claimed sync lock")
return true
end
if lock.Value and lock.Value ~= Players.LocalPlayer and lock.Value.Parent then
Log.trace("Found existing sync lock owned by {}", lock.Value)
return false, lock.Value
end
lock.Value = Players.LocalPlayer
Log.trace("Claimed existing sync lock")
return true
end
function App:releaseSyncLock()
local lock = ServerStorage:FindFirstChild("__Rojo_SessionLock")
if not lock then
Log.trace("No sync lock found, assumed released")
return
end
if lock.Value == Players.LocalPlayer then
lock.Value = nil
Log.trace("Released sync lock")
return
end
Log.trace("Could not relase sync lock because it is owned by {}", lock.Value)
end
function App:startSession()
local claimedLock, priorOwner = self:claimSyncLock()
if not claimedLock then
local msg = string.format("Could not sync because user '%s' is already syncing", tostring(priorOwner))
Log.warn(msg)
self:addNotification(msg, 10)
self:setState({
appStatus = AppStatus.Error,
errorMessage = msg,
toolbarIcon = Assets.Images.PluginButtonWarning,
})
return
end
local host, port = self:getHostAndPort()
local sessionOptions = {
@@ -155,6 +216,7 @@ function App:startSession()
self:addNotification(string.format("Connected to session '%s' at %s.", details, address), 5)
elseif status == ServeSession.Status.Disconnected then
self.serveSession = nil
self:releaseSyncLock()
-- Details being present indicates that this
-- disconnection was from an error.

View File

@@ -115,6 +115,12 @@ local function diff(instanceMap, virtualInstances, rootId)
local childId = instanceMap.fromInstances[childInstance]
if childId == nil then
if childInstance.Archivable == false then
-- We don't remove instances that aren't going to be saved anyway,
-- such as the Rojo session lock value.
continue
end
-- This is an existing instance not present in the virtual DOM.
-- We can mark it for deletion unless the user has asked us not
-- to delete unknown stuff.