diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 2f094558..40af8058 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -233,4 +233,19 @@ function ApiContext:retrieveMessages() end) end +function ApiContext:open(id) + local url = ("%s/api/open/%s"):format(self.__baseUrl, id) + + return Http.post(url, "") + :andThen(rejectFailedRequests) + :andThen(Http.Response.json) + :andThen(function(body) + if body.sessionId ~= self.__sessionId then + return Promise.reject("Server changed ID") + end + + return nil + end) +end + return ApiContext \ No newline at end of file diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index c859f8f0..43237cd4 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -33,6 +33,14 @@ local VALUES = { [Environment.Test] = false, }, }, + UnstableOpenScriptsExternally = { + type = "BoolValue", + values = { + [Environment.User] = false, + [Environment.Dev] = false, + [Environment.Test] = false, + }, + }, } local CONTAINER_NAME = "RojoDevSettings" .. Config.codename @@ -144,6 +152,10 @@ function DevSettings:twoWaySyncEnabled() return getValue("UnstableTwoWaySync") end +function DevSettings:alwaysOpenScriptsExternally() + return getValue("UnstableOpenScriptsExternally") +end + function _G.ROJO_DEV_CREATE() DevSettings:createDevSettings() end diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index b13b351e..36fb61b2 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -1,3 +1,5 @@ +local StudioService = game:GetService("StudioService") + local Log = require(script.Parent.Parent.Log) local Fmt = require(script.Parent.Parent.Fmt) local t = require(script.Parent.Parent.t) @@ -57,12 +59,26 @@ function ServeSession.new(options) local instanceMap = InstanceMap.new(onInstanceChanged) local reconciler = Reconciler.new(instanceMap) + local connections = {} + + local connection = StudioService + :GetPropertyChangedSignal("ActiveScript") + :Connect(function() + local activeScript = StudioService.ActiveScript + + if activeScript ~= nil then + self:__onActiveScriptChanged(activeScript) + end + end) + table.insert(connections, connection) + self = { __status = Status.NotStarted, __apiContext = options.apiContext, __reconciler = reconciler, __instanceMap = instanceMap, __statusChangedCallback = nil, + __connections = connections, } setmetatable(self, ServeSession) @@ -108,6 +124,37 @@ function ServeSession:stop() self:__stopInternal() end +function ServeSession:__onActiveScriptChanged(activeScript) + if not DevSettings:alwaysOpenScriptsExternally() then + Log.trace("Not opening script {} because feature not enabled.", activeScript) + + return + end + + if self.__status ~= Status.Connected then + Log.trace("Not opening script {} because session is not connected.", activeScript) + + return + end + + local scriptId = self.__instanceMap.fromInstances[activeScript] + if scriptId == nil then + Log.trace("Not opening script {} because it is not known by Rojo.", activeScript) + + return + end + + Log.debug("Trying to open script {} externally...", activeScript) + + -- Force-close the script inside Studio + local existingParent = activeScript.Parent + activeScript.Parent = nil + activeScript.Parent = existingParent + + -- Notify the Rojo server to open this script + self.__apiContext:open(scriptId) +end + function ServeSession:__onInstanceChanged(instance, propertyName) if not DevSettings:twoWaySyncEnabled() then return @@ -200,6 +247,11 @@ function ServeSession:__stopInternal(err) self:__setStatus(Status.Disconnected, err) self.__apiContext:disconnect() self.__instanceMap:stop() + + for _, connection in ipairs(self.__connections) do + connection:Disconnect() + end + self.__connections = {} end function ServeSession:__setStatus(status, detail)