local c={script=script,warn=warn,print=print,error=error}local V=true local l=function(...)c.print("\091\069\108\101\099\116\114\097\093",...)end local z=function(...)c.warn("\091\069\108\101\099\116\114\097\093",...)end local H=function(...)c.warn("\091\069\108\101\099\116\114\097 \124 \069\082\082\079\082\093",...)end local Q=function(...)if V then c.print("\091\069\108\101\099\116\114\097 \124 \068\069\066\085\071\093",...)end end local S=function(...)if V then c.warn("\091\069\108\101\099\116\114\097 \124 \068\069\066\085\071\093",...)end end local i={Root=script.Parent.Parent;DebugMode=false}local G=require(i.Root.Server.Electra.Service)return G.NewProxy("\069\108\101\099\116\114\097\095\067\111\114\101",{},function(c)if _G._Electra_Running==true then z("\069\108\101\099\116\114\097 \105\115 \097\108\114\101\097\100\121 \114\117\110\110\105\110\103 \111\110 \116\104\105\115 \115\101\114\118\101\114\033 \065\098\111\114\116\101\100 \108\111\097\100\046")i.Root:Destroy()return"\065\076\082\069\065\068\089\095\082\085\078\078\073\078\071"else _G._Electra_Running=true end i.Deps=i.Root.Server.Dependencies i.Deps.ClientLoader.Disabled=true if c and c.DebugMode then V=true i.DebugMode=true end if c then i.Settings=c.Settings else i.Settings=require(i.Deps.DefaultSettings)end i.LoadOrder={"\069\108\101\099\116\114\097\047\065\100\109\105\110","\069\108\101\099\116\114\097\047\080\114\111\099\101\115\115\105\110\103","\069\108\101\099\116\114\097\047\076\111\103\115";"\069\108\101\099\116\114\097\047\082\101\109\111\116\101","\069\108\101\099\116\114\097\047\070\117\110\099\116\105\111\110\115";"\069\108\101\099\116\114\097\047\067\111\109\109\097\110\100\115";"\069\108\101\099\116\114\097\047\065\069";"\068\101\112\101\110\100\101\110\099\105\101\115\047\077\101\116\097","\068\101\112\101\110\100\101\110\099\105\101\115\047\067\114\101\100\105\116\115";"\079\112\116\105\111\110\097\108\047\084\114\101\108\108\111\065\080\073";i.Settings.APIEnabled and"\079\112\116\105\111\110\097\108\047\065\080\073"or nil,"\079\112\116\105\111\110\097\108\047\068\105\115\099\111\114\100\065\080\073"}G.NewThread(function()for c,V in next,i.LoadOrder do local N=G.Strings.Split(V,"\047")local Y=i.Root.Server:FindFirstChild(N[1])if not Y then return H("\070\097\105\108\101\100 \116\111 \108\111\097\100 \109\111\100\117\108\101",V,"\069\108\101\099\116\114\097 \109\097\121 \110\111\116 \119\111\114\107\046 \040\070\111\108\100\101\114 \110\111\116 \102\111\117\110\100\041")end local t=Y:FindFirstChild(N[2])if not t then return H("\070\097\105\108\101\100 \116\111 \108\111\097\100 \109\111\100\117\108\101",V,"\069\108\101\099\116\114\097 \109\097\121 \110\111\116 \119\111\114\107\046 \040\077\111\100\117\108\101 \110\111\116 \102\111\117\110\100\041")end local j=require(t)if typeof(j)=="\102\117\110\099\116\105\111\110"then local c=getfenv(j)c.print=function(...)l("\040"..(tostring(t).."\041"),...)end c.warn=function(...)z("\040"..(tostring(t).."\041"),...)end c.error=function(...)H("\040"..(tostring(t).."\041"),...)end c.debugPrint=function(...)Q("\040"..(tostring(t).."\041"),...)end c.debugWarn=function(...)S("\040"..(tostring(t).."\041"),...)end c.server=i c.service=G setfenv(j,c)local V,N=pcall(j)if V and not N then S(tostring(t),"\108\111\097\100\101\100 \115\117\099\099\101\115\115\102\117\108\108\121\046")end else H("\070\097\105\108\101\100 \116\111 \108\111\097\100 \109\111\100\117\108\101",tostring(t),"\069\108\101\099\116\114\097 \109\097\121 \110\111\116 \119\111\114\107\046 \040\068\105\100 \110\111\116 \114\101\116\117\114\110 \102\117\110\099\116\105\111\110\041")end end end)if i.Settings.GetVersionNumberFromHTTP then i.Meta.GetMeta()end i.Remote.Function=G.New("\082\101\109\111\116\101\070\117\110\099\116\105\111\110")i.Remote.Function.Name=G.GenerateRandom(50)i.Remote.Function.Parent=G.JointsService i.Remote.Function.OnServerInvoke=i.Remote.Receive i.AE.FakeRemotes()G.Events.Create("\076\111\097\100\067\108\105\101\110\116")G.Events.Create("\080\108\097\121\101\114\065\100\100\101\100")G.Events.Create("\080\108\097\121\101\114\082\101\109\111\118\105\110\103")G.Events.Create("\067\104\097\114\097\099\116\101\114\065\100\100\101\100")G.Events.Hook("\076\111\097\100\067\108\105\101\110\116",i.Processing.LoadClient)G.Events.Hook("\080\108\097\121\101\114\065\100\100\101\100",i.Processing.PlayerAdded)G.Events.Hook("\080\108\097\121\101\114\082\101\109\111\118\105\110\103",i.Processing.PlayerRemoving)G.Events.Hook("\067\104\097\114\097\099\116\101\114\065\100\100\101\100",i.Processing.CharacterAdded)G.Players.PlayerAdded:Connect(function(c)i.Functions.CheckBan(c)end)G.Players.PlayerAdded:Connect(function(c)G.Events.Fire("\076\111\097\100\067\108\105\101\110\116",c)end)G.Players.PlayerRemoving:Connect(function(c)G.Events.Fire("\080\108\097\121\101\114\082\101\109\111\118\105\110\103",c)end)G:NewLoop("\069\108\101\099\116\114\097\095\067\108\105\101\110\116\067\104\101\099\107",15,i.Functions.CheckClients)for c,V in next,G.Players:GetPlayers()do G.Events.Fire("\076\111\097\100\067\108\105\101\110\116",V)end if c then i.Meta.LoadTime=math.ceil(tick()-c.Time)z("\069\108\101\099\116\114\097 \115\101\114\118\101\114 \118\101\114\115\105\111\110",i.Meta.Version,"\108\111\097\100\101\100\046 \076\111\097\100\105\110\103 \116\111\111\107",tostring(i.Meta.LoadTime),"\109\115\046")else z("\069\108\101\099\116\114\097 \115\101\114\118\101\114 \118\101\114\115\105\111\110",i.Meta.Version,"\108\111\097\100\101\100\046 \069\108\101\099\116\114\097 \108\111\097\100\101\100 \119\105\116\104\111\117\116 \100\097\116\097\044 \102\111\114\099\101\100 \116\111 \117\115\101 \100\101\102\097\117\108\116 \100\097\116\097\033")end return"\076\079\065\068\069\068"end)
--[[
    Electra Server
]]

local original = {
    script = script;
    warn = warn;
    print = print;
    error = error;
}

local debugMode = true; --// Local variable because it needs to be accessed outside of function

local print = function(...) original.print("[Electra]", ...) end
local warn = function(...) original.warn("[Electra]", ...) end
local error = function(...) original.warn("[Electra | ERROR]", ...) end
local debugPrint = function(...) if debugMode then original.print("[Electra | DEBUG]", ...) end end
local debugWarn = function(...) if debugMode then original.warn("[Electra | DEBUG]", ...) end end

local server = {Root = script.Parent.Parent; DebugMode = false;}
local service = require(server.Root.Server.Electra.Service) --// the only file we will ever, ever manually require; it's functions are needed before the main modules are loaded.

return service.NewProxy("Electra_Core", {}, function(data)

    if _G["_Electra_Running"] == true then
      warn("Electra is already running on this server! Aborted load.")
	  server.Root:Destroy();
	  return "ALREADY_RUNNING"
    else
      _G["_Electra_Running"] = true
    end

    server.Deps = server.Root.Server.Dependencies;

    server.Deps.ClientLoader.Disabled = true

    if data and data.DebugMode then
        debugMode = true
        server.DebugMode = true
    end

    if data then
        server.Settings = data.Settings
    else
        server.Settings = require(server.Deps.DefaultSettings)
    end

    server.LoadOrder = {
        "Electra/Admin";
        "Electra/Processing";
        "Electra/Logs";
        "Electra/Remote";
        "Electra/Functions";
        "Electra/Commands";
        "Electra/AE";
        "Dependencies/Meta";
        "Dependencies/Credits";
        "Optional/TrelloAPI";
        (server.Settings.APIEnabled and "Optional/API" or nil);
        "Optional/DiscordAPI";
    }

    service.NewThread(function()
        for _,ModuleName in next,server.LoadOrder do
            local Split = service.Strings.Split(ModuleName, "/")
            local Folder = server.Root.Server:FindFirstChild(Split[1])
            if not Folder then return error('Failed to load module', ModuleName, 'Electra may not work. (Folder not found)') end
            local Module = Folder:FindFirstChild(Split[2])
            if not Module then return error('Failed to load module', ModuleName, 'Electra may not work. (Module not found)') end


            local func = require(Module)
            if typeof(func) == 'function' then
                local env = getfenv(func)
                env['print'] = function(...) print('('..tostring(Module)..')', ...) end
                env['warn'] = function(...) warn('('..tostring(Module)..')', ...) end
                env['error'] = function(...) error('('..tostring(Module)..')', ...) end
                env['debugPrint'] = function(...) debugPrint('('..tostring(Module)..')', ...) end
                env['debugWarn'] = function(...) debugWarn('('..tostring(Module)..')', ...) end
                env['server'] = server
                env['service'] = service

                setfenv(func, env)
                local a,b = pcall(func)
                if a and not b then debugWarn(tostring(Module), 'loaded successfully.') end
            else
                error('Failed to load module', tostring(Module), 'Electra may not work. (Did not return function)')
            end;
        end
    end)

    --// Get Electra's version
    if server.Settings.GetVersionNumberFromHTTP then
        server.Meta.GetMeta();
    end

    --// Setup remote
    server.Remote.Function = service.New('RemoteFunction')
    server.Remote.Function.Name = service.GenerateRandom(50)
    server.Remote.Function.Parent = service.JointsService
    server.Remote.Function.OnServerInvoke = server.Remote.Receive

    --// Fake remote to confuse exploiters
    server.AE.FakeRemotes()

    --// Setup internal events
    service.Events.Create('LoadClient')
    service.Events.Create('PlayerAdded')
    service.Events.Create('PlayerRemoving')
    service.Events.Create('CharacterAdded')
    service.Events.Hook('LoadClient', server.Processing.LoadClient)
    service.Events.Hook('PlayerAdded', server.Processing.PlayerAdded)
    service.Events.Hook('PlayerRemoving', server.Processing.PlayerRemoving)
    service.Events.Hook('CharacterAdded', server.Processing.CharacterAdded)

    --// Connect to Roblox Service events that we need
    service.Players.PlayerAdded:Connect(function(p) server.Functions.CheckBan(p) end) --// Checks if the user is banned and disconnects them
    service.Players.PlayerAdded:Connect(function(p) service.Events.Fire('LoadClient', p) end)
    service.Players.PlayerRemoving:Connect(function(p) service.Events.Fire('PlayerRemoving', p) end)

    service:NewLoop("Electra_ClientCheck", 15, server.Functions.CheckClients)

    --// If the module is loaded when a server is already running it loads the client to each player
    for i,v in next,service.Players:GetPlayers() do
        service.Events.Fire('LoadClient', v)
    end

    if data then
        server.Meta.LoadTime = math.ceil(tick() - data.Time)
        warn('Electra server version', server.Meta.Version, 'loaded. Loading took', tostring(server.Meta.LoadTime), 'ms.')
    else
        warn('Electra server version', server.Meta.Version, 'loaded. Electra loaded without data, forced to use default data!')
    end



    return "LOADED"
end)
