Technical: Short overview about Cross-Plugin Communication, StudioService as a location for interfaces

Default Roblox Studio seems to have this

image

image

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 :person_shrugging: 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. :person_shrugging:

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.

4 Likes