HotSwap Plugin: Speed up plugin development

One day, I decided that saving a plugin to the plugins folder in order to test it was too tedious, so I wrote the most meta plugin ever.

Screenshot

Links

Description

HotSwap can be used to speed up plugin development by running the plugin immediately, without the need to save to the plugins folder. The HotSwap dialog can be toggled by clicking the HotSwap button in the Plugins menu. The dialog is used to select your plugin in the explorer panel, and to set it as the current “hotswap” (the object to be run as a plugin). Selecting nothing will remove the current hotswap. Once you have the hotswap set, you can run it by clicking the studio’s Run button. All enabled Scripts and LocalScripts that are descendants of the hotswap will be executed in a plugin-like environment.

Hotswap will display messages at the bottom of the screen when certain events occur. These will keep you informed when you run a hotswap, when the hotswap is moved or goes into an invalid state, or when any other notable events happen.

Noteworthy things

If the name of the selection or hotswap is larger than the text field, you can click and drag the dialog’s right border to change its size.

Like with normal plugins, all descendant Scripts and LocalScripts will run. Also like normal plugins, they will only run if their Disabled property is set to false.

HotSwap runs the selected plugin in an environment that is almost exactly the same as a normal plugin environment. There are differences, though:

  • Error messages in general wont be exactly the same. HotSwap still tries to display the name of the script and the line number, so you should be able to figure out where the error occurred. Same goes for stack traces.
  • Error messages from getfenv and setfenv can and will be wildly incorrect. Due to how loadstring works, getfenv and setfenv have to be sandboxed so that HotSwap wont interfere with environment manipulation. This seems to work sufficiently as far as I can tell (I’ll cry if it doesn’t). However, due to a bug with pcall, errors cannot be propagated correctly through the sandboxed functions. So, if you can’t understand an error emitted by either of these functions, then blame roblox and its crazy bugs (more rationally, just run the plugin without HotSwap to get the correct error).
  • The ran plugin has an asset ID of 0 instead of -1, so settings will be stored in a different folder from usual (this ended up being rather convenient for developing HotSwap via HotSwap).

Other quirks:

  • Since you have to use the Run button to run the plugin, the actual scripts will run if they can. So it’s a good idea to develop your plugin in a container that doesn’t run scripts, such as ServerStorage.
  • If a NetworkServer is in-game, then HotSwap will not work unless ServerScriptService.LoadstringEnabled is set to true. HotSwap will tell if loadstring is disabled, so it shouldn’t be too much of an issue.

Uninteresting crap

HotSwap works by saving a reference to the hotswap as a list containing the names of the object and its ancestors. Then, whenever the plugin is loaded and the game is detected as running, this list is recursively searched using FindFirstChild. If the object is found, then all of the object’s descendants are traversed, and any found scripts are run.

Because of how a hotswap is referenced, other objects that have matching names can interfere, so HotSwap tries its best to make sure you can’t select an object that wont be detected properly. As a totally unnecessary feature, once you have a hotswap selected, the plugin will detect changes to the hotswap’s name and ancestry. So if you move it around in the game tree, the plugin will keep the reference updated. It will also detect when the hotswap goes into an invalid state, such as when the name of another object matches and overrides the name of the hotswap, when you select an object that can’t be indexed (such as CSGDictionaryService), or when the hotswap is removed from the game tree.

3 Likes

TL;DR, sorry :stuck_out_tongue:

I see Plugin Folder. Does this mean that this plugin works only for Local plugins that have to be .lua and saved in the folder, or does this go for any?

[quote] TL;DR, sorry :stuck_out_tongue:

I see Plugin Folder. Does this mean that this plugin works only for Local plugins that have to be .lua and saved in the folder, or does this go for any? [/quote]

This lets you run plugins of the rbxm format. So you’d have a model containing the plugin content in studio, you can then select it and run it through the plugin.

[quote] TL;DR, sorry :stuck_out_tongue:

I see Plugin Folder. Does this mean that this plugin works only for Local plugins that have to be .lua and saved in the folder, or does this go for any? [/quote]

This lets you run plugins of the rbxm format. So you’d have a model containing the plugin content in studio, you can then select it and run it through the plugin.[/quote]
Thanks. Since I do plugin development, this will be helpful.

I assume not because you’re not running from the actual script, but I will ask anyway. Is there any way to use the debugger with Hotswap plugins? I have been working with a nightmare of a plugin recently, and the debugger would really help.

The debugger only works on script objects. Hotswap runs plugins by using loadstring, and since the thread running hotswap doesn’t have an associated script object, it can’t be debugged. It probably is possible to get something that can be debugged, but it would require a lot of work to implement, and would be neither stable nor friendly to use.