if not plugin then error("\072\111\116 \114\101\108\111\097\100\101\114 \109\117\115\116 \098\101 \101\120\101\099\117\116\101\100 \097\115 \097 \112\108\117\103\105\110\033")end local n=require(script.Parent.Config)local Z=n.isDevBuild local w=game:GetService("\083\101\114\118\101\114\083\116\111\114\097\103\101")local i="\077\097\122\101\071\101\110\101\114\097\116\111\114\080\108\117\103\105\110"local X=w:FindFirstChild(i)local G=script.Parent.Parent local K=G local V=K local F={_toolbars={};_pluginGuis={};_buttons={};_watching={},_beforeUnload=nil}function F.toolbar(Z,n)if Z._toolbars[n]then return Z._toolbars[n]end local w=plugin:CreateToolbar(n)Z._toolbars[n]=w return w end function F.GetSetting(Z,n)return plugin:GetSetting(n)end function F.SetSetting(Z,n)return plugin:SetSetting(n)end function F.button(X,n,Z,w,i)local G=X._buttons[n]if G then local n=G[Z]if n then return n end else G={}X._buttons[n]=G end local K=n:CreateButton(Z,w,i)G[Z]=K return K end function F.createDockWidgetPluginGui(Z,n,...)if Z._pluginGuis[n]then return Z._pluginGuis[n]end local w=plugin:CreateDockWidgetPluginGui(n,...)Z._pluginGuis[n]=w return w end function F.beforeUnload(Z,n)Z._beforeUnload=n end function F._load(Z,n)local w=V:WaitForChild("\080\108\117\103\105\110")local i=w:WaitForChild("\077\097\105\110")local X,G=pcall(require,i)if not X then warn("\080\108\117\103\105\110 \102\097\105\108\101\100 \116\111 \108\111\097\100\058 "..G)return end local K=G X,G=pcall(K,F,n)if not X then warn("\080\108\117\103\105\110 \102\097\105\108\101\100 \116\111 \114\117\110\058 "..G)return end end function F.unload(n)if n._beforeUnload then local Z=n._beforeUnload()n._beforeUnload=nil return Z end end function F._reload(n)local Z=n:unload()V=K:Clone()n:_load(Z)end function F._watch(Z,n)if Z._watching[n]then return end if n==script then return end local w=n.Changed:Connect(function(w)print("\082\101\108\111\097\100\105\110\103 \100\117\101 \116\111",n:GetFullName())Z:_reload()end)local i=n.ChildAdded:Connect(function(n)Z:_watch(n)end)local X={w,i}Z._watching[n]=X for n,w in ipairs(n:GetChildren())do Z:_watch(w)end end if Z then if X~=nil then K=X V=K else warn("\077\097\122\101\071\101\110\101\114\097\116\111\114 \100\101\118\101\108\111\112\109\101\110\116 \115\111\117\114\099\101 \105\115 \110\111\116 \112\114\101\115\101\110\116\044 \114\117\110\110\105\110\103 \117\115\105\110\103 \098\117\105\108\116-\105\110 \115\111\117\114\099\101\046 \087\097\105\116\105\110\103 \102\111\114 "..(i.." \105\110\116\111 \083\101\114\118\101\114\083\116\111\114\097\103\101\046"))local n n=w.ChildAdded:Connect(function(Z)print("\083\101\114\118\101\114\083\116\111\114\097\103\101 \099\104\097\110\103\101\100",Z.Name)if Z.Name==i then print("\071\111\116 "..(i.."\082\101\108\111\097\100\105\110\103 \112\108\117\103\105\110\046"),Z.Name)n:Disconnect()K=w:WaitForChild(i)V=K F:_load()F:_watch(K)end end)end end F:_load()if Z then F:_watch(K)end
-- Taken from https://github.com/tiffany352/Roblox-Tag-Editor/blob/bd48fb7ceea6bcd1cd9c515891ae4eb4eb9d1a71/src/Loader.server.lua#L24

-- Sanity check.
if not plugin then
	error('Hot reloader must be executed as a plugin!')
end

-- Change to true to enable hot reloading support. Opening a place
-- containing the code synced via Rojo will cause the plugin to be
-- reloaded in edit mode. (No need for play solo or the hotswap plugin.)
local Config = require(script.Parent.Config)
local useDevSource = Config.isDevBuild
local ServerStorage = game:GetService('ServerStorage')
local PluginFolderName = 'MazeGeneratorPlugin'
local devSource = ServerStorage:FindFirstChild(PluginFolderName)

-- The source that's shipped integrated into the plugin.
local builtinSource = script.Parent.Parent

-- `source` is where we should watch for changes.
-- `currentRoot` is the clone we make of source to avoid require()
-- returning stale values.
local source = builtinSource
local currentRoot = source

local PluginFacade = {
	_toolbars = {},
	_pluginGuis = {},
	_buttons = {},
	_watching = {},
	_beforeUnload = nil,
}

--[[
	Abstraction for plugin:CreateToolbar
]]
function PluginFacade:toolbar(name)
	if self._toolbars[name] then
		return self._toolbars[name]
	end

	local toolbar = plugin:CreateToolbar(name)

	self._toolbars[name] = toolbar

	return toolbar
end
function PluginFacade:GetSetting(name)
	return plugin:GetSetting(name)
end
function PluginFacade:SetSetting(name)
	return plugin:SetSetting(name)
end

--[[
	Abstraction for toolbar:CreateButton
]]
function PluginFacade:button(toolbar, name, tooltip, icon)
	local existingButtons = self._buttons[toolbar]

	if existingButtons then
		local existingButton = existingButtons[name]

		if existingButton then
			return existingButton
		end
	else
		existingButtons = {}
		self._buttons[toolbar] = existingButtons
	end

	local button = toolbar:CreateButton(name, tooltip, icon)

	existingButtons[name] = button

	return button
end

--[[
	Wrapper around plugin:CreatePluginGui
]]
function PluginFacade:createDockWidgetPluginGui(name, ...)
	if self._pluginGuis[name] then
		return self._pluginGuis[name]
	end

	local gui = plugin:CreateDockWidgetPluginGui(name, ...)
	self._pluginGuis[name] = gui

	return gui
end

--[[
	Sets the method to call the next time the system tries to reload
]]
function PluginFacade:beforeUnload(callback)
	self._beforeUnload = callback
end

function PluginFacade:_load(savedState)
	local Plugin = currentRoot:WaitForChild('Plugin')
	local Main = Plugin:WaitForChild('Main')
	local ok, result = pcall(require, Main)

	if not ok then
		warn('Plugin failed to load: ' .. result)
		return
	end

	local MainPluginScript = result

	ok, result = pcall(MainPluginScript, PluginFacade, savedState)

	if not ok then
		warn('Plugin failed to run: ' .. result)
		return
	end
end

function PluginFacade:unload()
	if self._beforeUnload then
		local saveState = self._beforeUnload()
		self._beforeUnload = nil

		return saveState
	end
end

function PluginFacade:_reload()
	local saveState = self:unload()
	currentRoot = source:Clone()

	self:_load(saveState)
end

function PluginFacade:_watch(instance)
	if self._watching[instance] then return end

	-- Don't watch ourselves!
	if instance == script then return end

	local connection1 = instance.Changed:Connect(function(prop)
		print('Reloading due to', instance:GetFullName())

		self:_reload()
	end)

	local connection2 = instance.ChildAdded:Connect(function(instance)
		self:_watch(instance)
	end)

	local connections = { connection1, connection2 }

	self._watching[instance] = connections

	for _, child in ipairs(instance:GetChildren()) do
		self:_watch(child)
	end
end

if useDevSource then
	if devSource ~= nil then
		source = devSource
		currentRoot = source
	else
		warn(
			'MazeGenerator development source is not present, running using built-in source. Waiting for ' .. PluginFolderName .. ' into ServerStorage.'
		)
		local connection
		connection = ServerStorage.ChildAdded:Connect(function(child)
			print('ServerStorage changed', child.Name)
			if child.Name == PluginFolderName then
				print('Got ' .. PluginFolderName .. 'Reloading plugin.', child.Name)
				connection:Disconnect()
				source = ServerStorage:WaitForChild(PluginFolderName)
				currentRoot = source
				PluginFacade:_load()
				PluginFacade:_watch(source)
			end
		end)
	end
end

PluginFacade:_load()
if useDevSource then
	PluginFacade:_watch(source)
end