local Q Q=setmetatable({Datamodel=game;Heartbeat=(game:GetService("\082\117\110\083\101\114\118\105\099\101")).Stepped;Loops={};Instances={},EventStorage={},New=function(...)local M=Instance.new(...)table.insert(Q.Instances,M)return M end;NewProxy=function(Q,M,J)assert(Q,"\115\101\114\118\105\099\101\046\078\101\119\080\114\111\120\121 \109\117\115\116 \098\101 \099\097\108\108\101\100 \119\105\116\104 \097 \110\097\109\101 \097\114\103\117\109\101\110\116")local w=newproxy(true)local v=getmetatable(w)v.__metatable=tostring(Q).."\095\069\108\101\099\116\114\097\083\101\114\118\101\114"if J~=nil then v.__call=function(Q,...)return J(...)end end v.__index=function(Q,M)return"\069\108\101\099\116\114\097\095\080\114\111\120\121"end for Q,M in next,M do v[Q]=M end return w end,NewLoop=function(Q,M,J,w,...)if not Q.Loops[M]then Q.Loops[M]=true spawn(function(...)while Q.Loops[M]do w(...)wait(J or 1)end end,...)else error("\076\111\111\112 \119\105\116\104 \110\097\109\101",M,"\097\108\114\101\097\100\121 \101\120\105\115\116\115\059 \073\116 \099\097\110\110\111\116 \098\101 \099\114\101\097\116\101\100\046")end end;StopLoop=function(Q,M)if not Q.Loops[M]then error("\076\111\111\112 \119\105\116\104 \110\097\109\101",M,"\100\111\101\115 \110\111\116 \101\120\105\115\116\059 \073\116 \099\097\110\110\111\116 \098\101 \115\116\111\112\112\101\100\046")else Q.Loops[M]=false end end;Strings={Split=function(Q,M)local J={}local w=M or" "local v=string.format("\040\091\094\037\115\093\043\041",w)string.gsub(Q,v,function(Q)J[#J+1]=Q end)return J end};Events={Create=function(M)assert(M,"\115\101\114\118\105\099\101\046\069\118\101\110\116\115\046\067\114\101\097\116\101 \109\117\115\116 \098\101 \099\097\108\108\101\100 \119\105\116\104 \097 \110\097\109\101")Q.EventStorage[M]={Event=Q.New("\066\105\110\100\097\098\108\101\069\118\101\110\116");HookedFunctions={}}Q.EventStorage[M].Event.Event:Connect(function(...)for Q,M in next,Q.EventStorage[M].HookedFunctions do M(...)end end)return Q.EventStorage[M].Event end,Get=function(M)assert(M,"\115\101\114\118\105\099\101\046\069\118\101\110\116\115\046\071\101\116 \109\117\115\116 \098\101 \099\097\108\108\101\100 \119\105\116\104 \097 \110\097\109\101")if Q.EventStorage[M]and Q.EventStorage[M].Event then return Q.EventStorage[M].Event end Q.EventStorage[M]={Event=Q.New("\066\105\110\100\097\098\108\101\069\118\101\110\116"),HookedFunctions={}}Q.EventStorage[M].Event.Event:Connect(function(...)for Q,M in next,Q.EventStorage[M].HookedFunctions do M(...)end end)return Q.EventStorage[M].Event end,Hook=function(M,J)assert(M,"\115\101\114\118\105\099\101\046\069\118\101\110\116\115\046\072\111\111\107 \109\117\115\116 \098\101 \099\097\108\108\101\100 \119\105\116\104 \097 \110\097\109\101")if not Q.EventStorage[M]then return error("\069\118\101\110\116 \119\105\116\104 \110\097\109\101",M,"\110\111\116 \102\111\117\110\100\046 \067\097\110\110\111\116 \104\111\111\107\046")end table.insert(Q.EventStorage[M].HookedFunctions,J)end;Fire=function(M,...)assert(M,"\115\101\114\118\105\099\101\046\069\118\101\110\116\115\046\070\105\114\101 \109\117\115\116 \098\101 \099\097\108\108\101\100 \119\105\116\104 \097 \110\097\109\101")if not Q.EventStorage[M]then return error("\069\118\101\110\116 \119\105\116\104 \110\097\109\101",M,"\110\111\116 \102\111\117\110\100\046 \067\097\110\110\111\116 \102\105\114\101\046")end Q.EventStorage[M].Event:Fire(...)end};GenerateRandom=function(Q)Q=Q or 10 local M=""for Q=1,Q,1 do M=M..string.format("\037\120",math.random(0,255))end return M end;Disconnect=function(Q,M)M=M or"\078\111 \107\105\099\107 \114\101\097\115\111\110 \115\112\101\099\105\102\105\101\100"Q:Kick("\n\069\108\101\099\116\114\097 - \068\105\115\099\111\110\110\101\099\116\101\100 \102\114\111\109 \115\101\114\118\101\114\058\n"..M)end;NewThread=function(Q,...)local M=table.pack(...)return coroutine.resume(coroutine.create(function()Q(table.unpack(M))end))end},{__index=function(Q,M)Q[M]=Q.Datamodel:GetService(M)return Q[M]end,__metatable="\069\108\101\099\116\114\097\083\101\114\118\101\114\095\083\101\114\118\105\099\101"})return Q
local service; service = setmetatable({

  Datamodel = game;
  Heartbeat = game:GetService('RunService').Stepped;
  Loops = {};
  Instances = {};
  EventStorage = {};

  New = function(...)
    local obj = Instance.new(...)
    table.insert(service.Instances, obj)
    return obj
  end;
  
  NewProxy = function(name, tab, func)
    assert(name, "service.NewProxy must be called with a name argument")
    local proxy = newproxy(true)
    local meta = getmetatable(proxy)
    
    meta.__metatable = tostring(name) .. "_ElectraServer"
    if func ~= nil then meta.__call = function(tab, ...) return func(...) end end
    meta.__index = function(t, i) return "Electra_Proxy" end

    for i,v in next,tab do
      meta[i] = v;
    end

    return proxy
  end;

  NewLoop = function(self, name, time, func, ...)
    if not self.Loops[name] then
      self.Loops[name] = true
      spawn(function(...) 
        while self.Loops[name] do
          func(...)
          wait(time or 1)
        end
      end, ...)
    else
      error('Loop with name', name, 'already exists; It cannot be created.')
    end
  end;

  StopLoop = function(self, name)
    if not self.Loops[name] then
      error('Loop with name', name, 'does not exist; It cannot be stopped.')
    else
      self.Loops[name] = false
    end
  end;

  Strings = {
    Split = function(s, sep)
      local t = {}
      local sep = sep or " "
      local pattern = string.format("([^%s]+)", sep)
      string.gsub(s, pattern, function(c) t[#t + 1] = c end)
      return t
    end;
  };

  Events = {
    Create = function(name)
      assert(name, "service.Events.Create must be called with a name")
      service.EventStorage[name] = {
        Event = service.New('BindableEvent');
        HookedFunctions = {};
      }

      service.EventStorage[name].Event.Event:Connect(function(...)
        for _,func in next,service.EventStorage[name].HookedFunctions do
          func(...)
        end
      end)

      return service.EventStorage[name].Event
    end;

    Get = function(name)
      assert(name, "service.Events.Get must be called with a name")
      if service.EventStorage[name] and service.EventStorage[name].Event then return service.EventStorage[name].Event end
      service.EventStorage[name] = {
        Event = service.New('BindableEvent');
        HookedFunctions = {};
      }

      service.EventStorage[name].Event.Event:Connect(function(...)
        for _, func in next, service.EventStorage[name].HookedFunctions do
          func(...)
        end
      end)

      return service.EventStorage[name].Event
    end;

    Hook = function(name, func)
      assert(name, "service.Events.Hook must be called with a name")
      if not service.EventStorage[name] then return error('Event with name', name, 'not found. Cannot hook.') end

      table.insert(service.EventStorage[name].HookedFunctions, func)
    end;

    Fire = function(name, ...)
      assert(name, "service.Events.Fire must be called with a name")
      if not service.EventStorage[name] then return error('Event with name', name, 'not found. Cannot fire.') end

      service.EventStorage[name].Event:Fire(...)
    end;
  };

  GenerateRandom = function(length)
    length = length or 10
    local toRet = ""
    for i = 1, length do
        toRet = toRet .. string.format("%x", math.random(0, 255))
    end
    return toRet
  end;

  Disconnect = function(p, msg)
    msg = msg or "No kick reason specified"
    p:Kick("\nElectra - Disconnected from server:\n" .. msg)
  end;

  NewThread = function(Function, ...)
    local Arguments = table.pack(...)
    return coroutine.resume(coroutine.create(function() Function(table.unpack(Arguments)) end))
  end;

},{

  __index = function(t, i)
    t[i] = t.Datamodel:GetService(i)
    return t[i]
  end;

  __metatable = "ElectraServer_Service";
  
})

return service