Default Roblox Studio seems to have this
Create a Local Plugin and put in this:
game.StudioService.DeveloperTools.Event:Connect(function(...) print(...) end)
And you can see that a few plugins cross-communicate with a debugging tool for Roact Tree visualization. In some way.
If done right, you could technically even use their internal utility no clue.
Â
Short Explanation
There’s Hidden Services, like the CoreGui. But there’s even more. Some of them are protected by Security Capabilities things such as StudioSdkService
.
But there’s StudioService
which is not protected, making it the ideal place for interfaces of any kinds. And you can access it through Plugins.
It doesn’t save stuff even if Archivable is set to true. Making it an ideal place to place random stuff inside of it, temporarily. Ideal because unlike CoreGui, StudioService only shows up if you have Hidden Services enabled in the Settings.
Temporarily in this context means that it won’t replicate when starting a game, and its content erase when re-opening the Place.
Â
It won’t show up in “Find All / Replace All,” unless all Hidden Services are enabled. Making it even more ideal to store dependencies such as React.
Â
With DataModel locations like these you can do the following:
- Store stuff
- Make other Plugins re-use the content
This is great, because if someone’s Plugins all use React. They could just make a second Plugin which will act as an Addon, which puts React inside of StudioService
and the Creator’s Plugins can just require it from there, instead of having to separately include it in their plugins all the time.
I don’t know how it affects Team Create.
Â
The StudioSdkService, has a function called :GetSdk()
, which apparently should return the Developer Framework or something, that Built-In Plugins could use instead, I think.
Not sure Built-In’s actually acquire their Modules from. Roblox’s RoTriever tool seems to just quadruplicate the amount of Roact and React modules across all the Plugins.
Example
Â
I made two example Plugin Script for demonstration. It sends a invokeable function through a BindableEvent to send metatables through.
Example Cross-Communicating Plugin
local Plugin = plugin :: Plugin
local toolbar = Plugin:CreateToolbar("Test")
local testButton = toolbar:CreateButton("test1", "A Test", "")
local bindable = game.StudioService:WaitForChild("BindTest1", 9999) :: BindableEvent
testButton.Click:Connect(function()
local name = {}
name.__index = name
function name.new()
local self = setmetatable({}, name)
self.test = "value"
return self
end
bindable:Fire(function()
return name.new()
end)
end)
local StudioService = game:GetService("StudioService")
local UNIQUE_BINDABLE_NAME = "BindTest1"
local bindable = StudioService:FindFirstChild(UNIQUE_BINDABLE_NAME) :: BindableEvent
if not bindable then
bindable = Instance.new("BindableEvent", StudioService)
bindable.Name = UNIQUE_BINDABLE_NAME
end
bindable.Event:Connect(function(a)
a = a()
print(a, getmetatable(a))
end)
Â
Should it be used?
I don’t know. A question of Performance. If you Studio freezes, then maybe reconsider something.
What I do know is that if you’re experimenting with higher Security Capability raised things, if a Plugin, owns a ModuleScript, the ModuleScript becomes the same Security Capability. So it’s something that would work for any kind of Plugin, per unique Security Capability.
I don’t know if Plugins are stored inside a DataModel, the only exception here is the PluginDebugService
, if enabled.
Â
If you open a game. A plugin only has to put something inside StudioService
once. If you start and stop the play test, the plugin won’t have to re-put things inside StudioService
.
However, each time a game runs, it can be triggering to re-put things inside. It doesn’t matter at that point, because plugins will reload anyways, if you have it enabled in your settings. And you can let your Plugins dynamically control this behavior as well.
Â
If you do plan to architecturize dependencies for public plugins inside that folder. Then create a unique name, and put everything inside a Folder.
Conclusion
It would actually be great to have a ReplicatedStorage, that replicates but is invisible, to store things inside the “Find All / Replace All” that you don’t want to appear. Because the Filter Function, doesn’t have a disclude option, nor do I feel like manually writing a filter for it all the times.