function module.GetProductInfo(j,h,c)local f,M=pcall(main.marketplaceService.GetProductInfo,main.marketplaceService,h,c or Enum.InfoType.Asset)return f and M end function module.SaveMap(c,h)local j=main.ss:FindFirstChild("\072\068\065\100\109\105\110\077\097\112\066\097\099\107\117\112")if j then local c=workspace:FindFirstChildOfClass("\084\101\114\114\097\105\110")main.mapBackupTerrain=c and c:CopyRegion(c.MaxExtents)if h then(main:GetModule("\099\102")):FormatAndFireNotice(h,"\083\097\118\101\077\097\112\049")end j:ClearAllChildren()for h,c in pairs(workspace:GetChildren())do if not c:IsA("\084\101\114\114\097\105\110")and(c.Archivable and(c.Name~="\072\068 \065\100\109\105\110"and(not c:IsA("\083\099\114\105\112\116")and not main.players:GetPlayerFromCharacter(c))))then local h=c:Clone()h.Parent=j end end if h then(main:GetModule("\099\102")):FormatAndFireNotice(h,"\083\097\118\101\077\097\112\050")end end end function module.ExecuteCommand(M,h,c,j,f)f=f or{}local P local d=f.ExtraDetails d=d or{}local T=f.UnFunction local o=j.ClientCommand local Q=j.ClientCommandToActivate local Y=j.Name local W={Function="\070\117\110\099\116\105\111\110",PreFunction="\080\114\101\070\117\110\099\116\105\111\110"}if T then for h,c in pairs(W)do W[h]="\085\110"..c end end local B=j[W.PreFunction]if B then local f,M=B(h,c,j,d)c=f or c d=M or d end local m=h local g=c[1]if g and(type(g)=="\117\115\101\114\100\097\116\097"and(typeof(g)=="\073\110\115\116\097\110\099\101"and(g.Parent==main.players and not j.FireToSpeaker)))then m=g end if o then if j.FireAllClients then main.signals.ExecuteClientCommand:FireAllClients({h;c;j.Name;f})else main.signals.ExecuteClientCommand:FireClient(m,{h;c,j.Name;f})end elseif Q then if T then main.pd[m].CommandsActive[Y]=nil main.signals.DeactivateClientCommand:FireClient(m,{Y})else d.Speed=tonumber(c[2])main.pd[m].CommandsActive[Y]=true main.signals.ActivateClientCommand:FireClient(m,{Y,d})end end local G=j[W.Function]if G then P=G(h,c,j,d)end return P end function module.FormatAndFireError2(f,h,c,j,...)local M=(main:GetModule("\099\102")):FormatNotice2(c,j,...)main.signals.Error:FireClient(h,M)end function module.FormatAndFireError(j,h,c,...)local f=(main:GetModule("\099\102")):FormatNotice(c,...)main.signals.Error:FireClient(h,f)end function module.FormatAndFireNotice2(f,h,c,j,...)local M=(main:GetModule("\099\102")):FormatNotice2(c,j,...)main.signals.Notice:FireClient(h,M)end function module.FormatAndFireNotice(j,h,c,...)local f=(main:GetModule("\099\102")):FormatNotice(c,...)main.signals.Notice:FireClient(h,f)end function module.Error(f,h,c,j)main.signals.Error:FireClient(h,{c;j})end function module.Notice(f,h,c,j)main.signals.Notice:FireClient(h,{c,j})end function module.GetAmountOfServers(h)local c="\071\101\116\083\101\114\118\101\114\115"..math.random(1,100000)local j=0 local f=main.messagingService:SubscribeAsync(c,function(h)j=j+1 end)main.messagingService:PublishAsync("\071\101\116\065\109\111\117\110\116\079\102\083\101\114\118\101\114\115",c)wait(.5)f:Disconnect()return j end function module.DisplayPollResults(j,h,c)main.signals.CreateMenu:FireClient(h,{MenuName="\112\111\108\108\082\101\115\117\108\116\115";Data=c;TemplateId=11})end function module.BeginPoll(j,h,c)if c==nil then c={}for h,j in pairs(main.players:GetChildren())do table.insert(c,j)end end local f={}local M={}local P=#c local d=Instance.new("\082\101\109\111\116\101\069\118\101\110\116")d.Name="\072\068\065\100\109\105\110\080\111\108\108"..h.PollId d.OnServerEvent:Connect(function(h,c)if f[h]then M[h]=c end end)d.Parent=workspace h.Remote=d for c,j in pairs(c)do f[j]=true main.signals.CreateMenu:FireClient(j,{MenuName="\112\111\108\108";Data=h,TemplateId=10})end for h=1,h.VoteTime+1,1 do wait(1)local c=0 for h,j in pairs(M)do c=c+1 end if c>=P then break end end local T={}for h=1,#h.Answers,1 do table.insert(T,0)end h.Results={}local o=0 local Q=0 for h,c in pairs(M)do local j=T[c]+1 if j>Q then Q=j end T[c]=j o=o+1 end local Y=P-o if Y>Q then Q=Y end for c,j in pairs(h.Answers)do local f=T[c]table.insert(h.Results,{Answer=j;Votes=f,Percentage=f/Q})end table.insert(T,Y)table.insert(h.Results,{Answer="\068\105\100 \078\111\116 \086\111\116\101",Votes=Y;Percentage=Y/Q})d:Destroy()return h,T end function module.GetBannedUserDetails(c,h)local j,f,M local P={main.serverBans;main.sd.Banland.Records}local d=os.time()for c,j in pairs(P)do for c,j in pairs(j)do local f=j.BanTime if not tonumber(f)or d<f-30 then local c=(main:GetModule("\099\102")):GetName(j.UserId)if string.sub(string.lower(c),1,#h)==h then return{c,j.UserId,j.Reason,j.BannedBy},j end end end end end function module.BanPlayer(j,h,c)local f=main.players:GetPlayerByUserId(h)local M=c.BanTime if tonumber(M)and os.time()>M-30 then local h=c.Server if h=="\067\117\114\114\101\110\116"then local h=(main:GetModule("\099\102")):FindUserIdInRecord(main.serverBans,c.UserId)if h then table.remove(main.serverBans,h)end else(main:GetModule("\083\121\115\116\101\109\068\097\116\097")):InsertStat("\066\097\110\108\097\110\100","\082\101\099\111\114\100\115\084\111\082\101\109\111\118\101",c)end else local h="\046"local j="\066\097\110 \076\101\110\103\116\104\058 \073\110\102\105\110\105\116\101"if c.BanTime~="\073\110\102\105\110\105\116\101"and f then local M=c.BanTime local P=os.date("\042\116",M)local d;(coroutine.wrap(function()local h,c=pcall(function()return main.signals.GetLocalDate:InvokeClient(f,M)end)if h then d=c else return end end))()local T=tick()repeat wait(.1)until d or tick()-T>2 if type(d)~="\116\097\098\108\101"then d={}end j=(main:GetModule("\099\102")):GetBanDateString(d,P)h="\044 \117\110\116\105\108\058"end local M="\097\108\108 \115\101\114\118\101\114\115"if c.Server=="\067\117\114\114\101\110\116"then M="\116\104\105\115 \115\101\114\118\101\114"end local P=c.Reason if P==""or P==" "then P="\069\109\112\116\121"else P="\'"..(P.."\'")end local d="\089\111\117\'\114\101 \098\097\110\110\101\100 \102\114\111\109 "..(M..(h..(" \n\n"..(j..("\n\n\082\101\097\115\111\110\058 "..(P.."\n"))))))if f then f:Kick(d)end end end function module.UpdateBanPlayerArg(j,h,c)local f,M,P=main.modules.Qualifiers:ParseQualifier(c,h)if P and#M>0 then c=M[1].Name end return c end function module.FindUserIdInRecord(j,h,c)for h,j in pairs(h)do if tostring(j.UserId)==tostring(c)then return h end end return false end function module.GetLog(c,h)local j={}for h,c in pairs(main.logs[h])do local f={}for h,c in pairs(c)do f[h]=c end table.insert(j,1,f)end return j end function module.PrivateMessage(f,h,c,j)local M=main.permissionToReplyToPrivateMessage[h]if M==nil then main.permissionToReplyToPrivateMessage[h]={}end main.permissionToReplyToPrivateMessage[h][c]=true;(main:GetModule("\099\102")):FormatAndFireNotice2(c,"\082\101\099\101\105\118\101\100\080\077",{"\080\077",h,j},h.Name)end function module.GetStat(j,h,c)if c then local j=h:FindFirstChild("\108\101\097\100\101\114\115\116\097\116\115")if j then local h=j:FindFirstChild(c)if h then return h end end end end function module.GetColorFromString(c,h)local j if h then h=string.lower(h)for c,f in pairs(main.settings.Colors)do local M=string.lower(f[1])if h==M then j=f[3]break end end if not j then for c,f in pairs(main.settings.Colors)do local M=string.lower(f[2])if h==string.sub(M,1,#h)then j=f[3]break end end end end return j end function module.RemoveControlPlr(c,h)if h and main.pd[h]then local c=main.pd[h].Items.ControlPlr if c then local j=c.FakePlayer.Head.CFrame c:Destroy()main.pd[h].Items.ControlPlr=nil;(main:GetModule("\077\111\114\112\104\072\097\110\100\108\101\114")):BecomeTargetPlayer(h,h.UserId)local f=(main:GetModule("\099\102")):GetHead(h)local M=(main:GetModule("\099\102")):GetFakeName(h)if f and M then M:Destroy()f.Transparency=0 f.CFrame=j end end end end function module.RemoveUnderControl(c,h)local j=main.pd[h].Items.UnderControl if j then j:Destroy()main.pd[h].Items.UnderControl=nil local c=(main:GetModule("\099\102")):GetHumanoid(h)if c then main.signals.SetCameraSubject:FireClient(h,c)h.Character.Parent=workspace end end end function module.TeleportPlayers(j,h,c)local f=(main:GetModule("\099\102")):GetHead(c)if f then local c=#h local j=2 for h,M in pairs(h)do local P=(main:GetModule("\099\102")):GetHead(M)local d=(f.CFrame*CFrame.new((-(c*(j/2))+h*j)-j/2,0,-4))*CFrame.Angles(0,math.rad(180),0)if P then(main:GetModule("\099\102")):UnSeatPlayer(M)P.CFrame=d end end end end function module.ConvertCharacterToRig(j,h,c)local f=(main:GetModule("\099\102")):GetHumanoid(h)local M=(main:GetModule("\099\102")):GetHead(h)if f and M then local j=main.server.Assets["\082\105\103"..c]:Clone()local f=j.Humanoid local P=M.CFrame j.Name=h.Name for h,c in pairs(h.Character:GetChildren())do if c:IsA("\065\099\099\101\115\115\111\114\121")or c:IsA("\080\097\110\116\115")or c:IsA("\083\104\105\114\116")or c:IsA("\083\104\105\114\116\071\114\097\112\104\105\099")or c:IsA("\066\111\100\121\067\111\108\111\114\115")then c.Parent=j elseif c.Name=="\072\101\097\100"and c:FindFirstChild("\102\097\099\101")then j.Head.face.Texture=c.face.Texture end end h.Character=j j.Parent=workspace j.Head.CFrame=P main.signals.ChangeMainVariable:FireClient(h,{"\104\117\109\097\110\111\105\100\082\105\103\084\121\112\101",Enum.HumanoidRigType[c]})end end function module.GetFakeName(c,h)for h,c in pairs(h.Character:GetChildren())do if c:IsA("\077\111\100\101\108")and c:FindFirstChild("\070\097\107\101\072\117\109\097\110\111\105\100")then return c end end end function module.CreateFakeName(j,h,c)local f=(main:GetModule("\099\102")):GetHead(h)if f then local j=module:GetFakeName(h)if not j then j=Instance.new("\077\111\100\101\108")local c=f:Clone()c.Name="\072\101\097\100"c.Parent=j c.face.Transparency=1 local M=Instance.new("\087\101\108\100\067\111\110\115\116\114\097\105\110\116")M.Part0=c M.Part1=f M.Parent=c local P=Instance.new("\072\117\109\097\110\111\105\100")P.Name="\070\097\107\101\072\117\109\097\110\111\105\100"P.Parent=j j.Parent=h.Character f.Transparency=1 end if c then j.Name=c end end end function module.RemoveEffect(j,h,c)local f="\072\068\065\100\109\105\110"..c if h.Character then for h,c in pairs(h.Character:GetDescendants())do if c.Name==f then c:Destroy()break end end end end function module.CreateEffect(j,h,c)local f=(main:GetModule("\099\102")):GetHRP(h)local M=f if c=="\070\111\114\099\101\070\105\101\108\100"then M=h.Character end if f then local h="\072\068\065\100\109\105\110"..c local j=M:FindFirstChild(h)if not j then j=Instance.new(c)j.Name=h j.Parent=M end end end function module.UnFreeze(c,h)local j=h[1]local f="\070\114\101\101\122\101\066\108\111\099\107"local M=main.pd[j].Items[f]if M then main.pd[j].Items[f]=nil;(main:GetModule("\099\102")):Movement(true,j);(main:GetModule("\099\102")):SetTransparency(j.Character,0)local h=(main:GetModule("\099\102")):GetHead(j)if h then h.CFrame=M.FreezeClone.Head.CFrame end local c=(main:GetModule("\099\102")):GetHumanoid(j)if c then main.signals.SetCameraSubject:FireClient(j,c)end M:Destroy()end end function module.FilterString(f,h,c,j)local M=""local P,d=pcall(function()M=main.chat:FilterStringAsync(h,c,j)end)if not P then M="\035\035\035\035"end return M end function module.FilterBroadcast(j,h,c)local f=""local M,P=pcall(function()f=main.chat:FilterStringForBroadcast(h,c)end)if not M then f="\035\035\035\035"end return f end function module.DonorNotice(j,h,c)if not c.PromptedDonor then(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\080\114\111\109\112\116\101\100\068\111\110\111\114",true);(main:GetModule("\099\102")):FormatAndFireNotice(h,"\087\101\108\099\111\109\101\068\111\110\111\114")end end function module.CheckAndRankToDonor(f,h,c,j)j=tostring(j)if not c.Donor and(j==tostring(main.products.Donor)or j==tostring(main.products.OldDonor))then(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\068\111\110\111\114",true)module:DonorNotice(h,c)end end function module.Unrank(c,h)(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\082\097\110\107",0)main.serverAdmins[h.Name]=nil;(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\083\097\118\101\082\097\110\107",false);(main:GetModule("\099\102")):FormatAndFireNotice(h,"\085\110\082\097\110\107")return"\085\110\114\097\110\107\101\100"end function module.GetRankType(c,h)local j="\083\101\114\118\101\114"local f=main.pd[h]if f then if f.AutomaticRank then j="\065\117\116\111"elseif f.SaveRank==true then j="\080\101\114\109"elseif main.serverAdmins[h.Name]==nil then j="\084\101\109\112"end end return j end function module.SetRank(M,h,c,j,f)(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\082\097\110\107",j);(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\065\117\116\111\109\097\116\105\099\082\097\110\107",false)local P="\114\097\110\107"if f=="\083\101\114\118\101\114"then main.serverAdmins[h.Name]=true elseif f=="\080\101\114\109"then(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\080\101\114\109\082\097\110\107\101\100\066\121",c);(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\083\097\118\101\082\097\110\107",true)main.serverAdmins[h.Name]=nil P="\112\101\114\109\082\097\110\107"elseif f=="\084\101\109\112"then main.serverAdmins[h.Name]=nil P="\116\101\109\112\082\097\110\107"end local d=(main:GetModule("\099\102")):GetRankName(j);(main:GetModule("\099\102")):FormatAndFireNotice(h,"\083\101\116\082\097\110\107",P,d)end function module.RankPlayerCommand(f,h,c,j)local M=c[1]local P=c[2]local d=main.pd[M].Rank local T=main.pd[h].Rank if P==0 then module:Unrank(M)return"\085\110\114\097\110\107\101\100"elseif T>P then module:SetRank(M,h.UserId,P,j)return"\082\097\110\107\101\100"end end function module.RankPlayerSimple(f,h,c,j)local M=main.pd[h]if tonumber(c)==nil then c=(main:GetModule("\099\102")):GetRankId(c)end if M.Rank<=c then if j then(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\065\117\116\111\109\097\116\105\099\082\097\110\107",c)end if M.Rank<c then(main:GetModule("\080\108\097\121\101\114\068\097\116\097")):ChangeStat(h,"\082\097\110\107",c)end end end return module

function module:GetProductInfo(AssetId, InfoType)
    local Success, Value = pcall(main.marketplaceService.GetProductInfo, main.marketplaceService, AssetId, InfoType or Enum.InfoType.Asset)
    return Success and Value
end

function module:SaveMap(speaker)
	local mapBackup = main.ss:FindFirstChild("HDAdminMapBackup")
	if mapBackup then
		local terrain = workspace:FindFirstChildOfClass("Terrain")
		main.mapBackupTerrain = terrain and terrain:CopyRegion(terrain.MaxExtents)
		if speaker then
			main:GetModule("cf"):FormatAndFireNotice(speaker, "SaveMap1")
		end
		mapBackup:ClearAllChildren()
		for a,b in pairs(workspace:GetChildren()) do
			if not b:IsA("Terrain") and b.Archivable and b.Name ~= "HD Admin" and not b:IsA("Script") and not main.players:GetPlayerFromCharacter(b) then
				local copy = b:Clone()
				copy.Parent = mapBackup
			end
		end
		if speaker then
			main:GetModule("cf"):FormatAndFireNotice(speaker, "SaveMap2")
		end
	end
end

function module:ExecuteCommand(speaker, args, command, other)
	other = other or {}
	local returnInfo
	local extraDetails = other.ExtraDetails
	extraDetails = extraDetails or {}
	local unFunction = other.UnFunction
	local clientCommand = command.ClientCommand
	local clientCommandToActivate = command.ClientCommandToActivate
	local commandName = command.Name
	
	--Decide if Undo or Normal function
	local functionTypes = {Function = "Function", PreFunction = "PreFunction"}
	if unFunction then
		for funcType, value in pairs(functionTypes) do
			functionTypes[funcType] = "Un"..value
		end
	end
	
	--Check for PreFunctions
	local PreFunction = command[functionTypes.PreFunction]
	if PreFunction then
		local newArgs, newExtraDetails = PreFunction(speaker, args, command, extraDetails)
		args = newArgs or args
		extraDetails = newExtraDetails or extraDetails
	end
	
	--Client Commands
	local plrToFireTo = speaker
	local checkForPlr = args[1]
	if checkForPlr and type(checkForPlr) == "userdata" and typeof(checkForPlr) == "Instance" and checkForPlr.Parent == main.players and not command.FireToSpeaker then
		plrToFireTo = checkForPlr
	end
	if clientCommand then
		if command.FireAllClients then
			main.signals.ExecuteClientCommand:FireAllClients{speaker, args, command.Name, other}
		else
			main.signals.ExecuteClientCommand:FireClient(plrToFireTo, {speaker, args, command.Name, other})
		end
	elseif clientCommandToActivate then
		if unFunction then
			main.pd[plrToFireTo].CommandsActive[commandName] = nil
			main.signals.DeactivateClientCommand:FireClient(plrToFireTo, {commandName})
		else
			extraDetails.Speed = tonumber(args[2])
			main.pd[plrToFireTo].CommandsActive[commandName] = true
			main.signals.ActivateClientCommand:FireClient(plrToFireTo, {commandName, extraDetails})
		end
	end
	
	--Execute Command Function
	local Function = command[functionTypes.Function]
	if Function then
		returnInfo = Function(speaker, args, command, extraDetails)
	end
	
	return returnInfo
end

function module:FormatAndFireError2(plr, noticeName, extraDetails, ...)
	local notice = main:GetModule("cf"):FormatNotice2(noticeName, extraDetails, ...)
	main.signals.Error:FireClient(plr, notice)
end

function module:FormatAndFireError(plr, noticeName, ...)
	local notice = main:GetModule("cf"):FormatNotice(noticeName, ...)
	main.signals.Error:FireClient(plr, notice)
end

function module:FormatAndFireNotice2(plr, noticeName, extraDetails, ...)
	local notice = main:GetModule("cf"):FormatNotice2(noticeName, extraDetails, ...)
	main.signals.Notice:FireClient(plr, notice)
end

function module:FormatAndFireNotice(plr, noticeName, ...)
	local notice = main:GetModule("cf"):FormatNotice(noticeName, ...)
	main.signals.Notice:FireClient(plr, notice)
end

function module:Error(player, title, message)
	main.signals.Error:FireClient(player, {title, message})
end

function module:Notice(player, title, message)
	main.signals.Notice:FireClient(player, {title, message})
end

function module:GetAmountOfServers()
	local topicId = "GetServers".. math.random(1,100000)
	local totalServers = 0
	local subFunc = main.messagingService:SubscribeAsync(topicId, function(message)
		totalServers = totalServers + 1
	end)
	main.messagingService:PublishAsync("GetAmountOfServers", topicId)
	wait(0.5)
	subFunc:Disconnect()
	return totalServers
end

function module:DisplayPollResults(plr, data)
	main.signals.CreateMenu:FireClient(plr, {MenuName = "pollResults", Data = data, TemplateId = 11})
end
function module:BeginPoll(data, participants)
	if participants == nil then
		participants = {}
		for i,plr in pairs(main.players:GetChildren()) do
			table.insert(participants, plr)
		end
	end
	
	local validPlayers = {}
	local votes = {}
	local totalParticipants = #participants
	
	--Setup remote
	local remote = Instance.new("RemoteEvent")
	remote.Name = "HDAdminPoll"..data.PollId
	remote.OnServerEvent:Connect(function(plr, answerId)
		if validPlayers[plr] then
			votes[plr] = answerId
		end
	end)
	remote.Parent = workspace
	data.Remote = remote
	
	--Vote players
	for i, plr in pairs(participants) do
		validPlayers[plr] = true
		main.signals.CreateMenu:FireClient(plr, {MenuName = "poll", Data = data, TemplateId = 10})
	end
	for i = 1, (data.VoteTime + 1) do
		wait(1)
		local totalVotes = 0
		for plr, answerId in pairs(votes) do
			totalVotes = totalVotes + 1
		end
		if totalVotes >= totalParticipants then
			break
		end
	end
	
	--Calculate results
	local scores = {}
	for i = 1, #data.Answers do
		table.insert(scores, 0)
	end
	data.Results = {}
	local totalVotes = 0
	local highestScore = 0
	for plr, answerId in pairs(votes) do
		local score = scores[answerId] + 1
		if score > highestScore then
			highestScore = score
		end
		scores[answerId] = score
		totalVotes = totalVotes + 1
	end
	local didNotVote = totalParticipants - totalVotes
	if didNotVote > highestScore then
		highestScore = didNotVote
	end
	for i,answer in pairs(data.Answers) do
		local answerVotes = scores[i]
		table.insert(data.Results, {
				Answer = answer;
				Votes = answerVotes;
				Percentage = answerVotes/highestScore;
			}
		)
	end
	table.insert(scores, didNotVote)
	table.insert(data.Results, {
		Answer = "Did Not Vote";
		Votes = didNotVote;
		Percentage = didNotVote/highestScore;
	})
	
	--Clean up
	remote:Destroy()
	
	--Return data
	return data, scores
		
end

function module:GetBannedUserDetails(plrArg)
	local targetName, targetId, targetReason
	local toScan = {main.serverBans, main.sd.Banland.Records}
	local timeNow = os.time()
	for section, records in pairs(toScan) do
		for i, record in pairs(records) do
			local banTime = record.BanTime
			if not tonumber(banTime) or timeNow < (banTime-30) then
				local userName = main:GetModule("cf"):GetName(record.UserId)
				if string.sub(string.lower(userName), 1, #plrArg) == plrArg then
					return {userName, record.UserId, record.Reason, record.BannedBy}, record
				end
			end
		end
	end
end

function module:BanPlayer(userId, record)
	local plr = main.players:GetPlayerByUserId(userId)
	--Check if ban expired
	local banTime = record.BanTime
	if tonumber(banTime) and os.time() > (banTime-30) then
		local server = record.Server
		if server == "Current" then
			local recordToRemovePos = main:GetModule("cf"):FindUserIdInRecord(main.serverBans, record.UserId)
			if recordToRemovePos then
				table.remove(main.serverBans, recordToRemovePos)
			end
		else
			main:GetModule("SystemData"):InsertStat("Banland", "RecordsToRemove", record)
		end
	-- Ban player
	else
		local untilString = "."
		local banDateString = "Ban Length: Infinite"
		if record.BanTime ~= "Infinite" and plr then
			local banTime = record.BanTime
			local serverDate = os.date("*t", banTime)
			local date
			coroutine.wrap(function()
				local success, clientDate = pcall(function() return main.signals.GetLocalDate:InvokeClient(plr, banTime) end)
				if success then
					date = clientDate
				else
					return
				end
			end)()
			local startTick = tick()
			repeat wait(0.1) until date or tick() - startTick > 2
			if type(date) ~= "table" then
				date = {}
			end
			banDateString = main:GetModule("cf"):GetBanDateString(date, serverDate)
			untilString = ", until:"
		end
		local serverType = "all servers"
		if record.Server == "Current" then
			serverType = "this server"
		end
		local reason = record.Reason
		if reason == "" or reason == " " then
			reason = "Empty"
		else
			reason = "'".. reason.."'"
		end
		local finalBanMessage = "You're banned from "..serverType..untilString.." \n\n"..banDateString.."\n\nReason: ".. reason.."\n"
		if plr then
			plr:Kick(finalBanMessage)
		end
	end
end

function module:UpdateBanPlayerArg(speaker, plrArg)
	local _, targetPlayersArray, individual = main.modules.Qualifiers:ParseQualifier(plrArg, speaker)
	if individual and #targetPlayersArray > 0 then
		plrArg = targetPlayersArray[1].Name
	end
	return plrArg
end

function module:FindUserIdInRecord(records, userId)
	for i,record in pairs(records) do
		if tostring(record["UserId"]) == tostring(userId) then
			return i
		end
	end
	return false
end

function module:GetLog(logName)
	local log = {}
	for _,record in pairs(main.logs[logName]) do
		local newRecord = {}
		for detailName, detail in pairs(record) do
			newRecord[detailName] = detail
		end
		table.insert(log, 1, newRecord)
	end
	return log
end

function module:PrivateMessage(sender, targetPlr, message)
	local senderPerms = main.permissionToReplyToPrivateMessage[sender]
	if senderPerms == nil then
		main.permissionToReplyToPrivateMessage[sender] = {}
	end
	main.permissionToReplyToPrivateMessage[sender][targetPlr] = true
	main:GetModule("cf"):FormatAndFireNotice2(targetPlr, "ReceivedPM", {"PM", sender, message}, sender.Name)
end

function module:GetStat(plr, statName)
	if statName then
		local leaderstats = plr:FindFirstChild("leaderstats")
		if leaderstats then
			local stat = leaderstats:FindFirstChild(statName)
			if stat then
				return stat
			end
		end
	end
end

function module:GetColorFromString(argToProcess)
	local finalColor
	if argToProcess then
		argToProcess = string.lower(argToProcess)
		for i, colorInfo in pairs(main.settings.Colors) do
			local shortName = string.lower(colorInfo[1])
			if (argToProcess == shortName) then
				finalColor = colorInfo[3]
				break
			end
		end
		if not finalColor then
			for i, colorInfo in pairs(main.settings.Colors) do
				local fullName = string.lower(colorInfo[2])
				if (argToProcess == string.sub(fullName,1,#argToProcess)) then
					finalColor = colorInfo[3]
					break
				end
			end
		end
	end
	return finalColor
end

function module:RemoveControlPlr(controller)
	if controller and main.pd[controller] then
		local controlPlr = main.pd[controller].Items["ControlPlr"]
		if controlPlr then
			local originalCFrame = controlPlr.FakePlayer.Head.CFrame
			controlPlr:Destroy()
			main.pd[controller].Items["ControlPlr"] = nil
			main:GetModule("MorphHandler"):BecomeTargetPlayer(controller, controller.UserId)
			local controllerHead = main:GetModule("cf"):GetHead(controller)
			local fakeName = main:GetModule("cf"):GetFakeName(controller)
			if controllerHead and fakeName then
				fakeName:Destroy()
				controllerHead.Transparency = 0
				controllerHead.CFrame = originalCFrame
			end
		end
	end
end

function module:RemoveUnderControl(plr)
	local underControl = main.pd[plr].Items["UnderControl"]
	if underControl then
		underControl:Destroy()
		main.pd[plr].Items["UnderControl"] = nil
		local plrHumanoid = main:GetModule("cf"):GetHumanoid(plr)
		if plrHumanoid then
			main.signals.SetCameraSubject:FireClient(plr, (plrHumanoid))
			--main:GetModule("cf"):SetTransparency(plr.Character, 0, true)
			--main:GetModule("cf"):Movement(true, plr)
			plr.Character.Parent = workspace
		end
	end
end

function module:TeleportPlayers(plrsToTeleport, targetPlr)
	local targetHead = main:GetModule("cf"):GetHead(targetPlr)
	if targetHead then
		local totalPlrs = #plrsToTeleport
		local gap = 2
		for i,plr in pairs(plrsToTeleport) do
			local head = main:GetModule("cf"):GetHead(plr)
			local targetCFrame = targetHead.CFrame * CFrame.new(-(totalPlrs*(gap/2))+(i*gap)-(gap/2), 0, -4) * CFrame.Angles(0, math.rad(180), 0)
			if head then
				main:GetModule("cf"):UnSeatPlayer(plr)
				head.CFrame = targetCFrame
			end
		end
	end
end

function module:ConvertCharacterToRig(plr, rigType)
	--
	local humanoid = main:GetModule("cf"):GetHumanoid(plr)
	local head = main:GetModule("cf"):GetHead(plr)
	if humanoid and head then
		local newRig = main.server.Assets["Rig"..rigType]:Clone()
		local newHumanoid = newRig.Humanoid
		local originalCFrame = head.CFrame
		newRig.Name = plr.Name
		for a,b in pairs(plr.Character:GetChildren()) do
			if b:IsA("Accessory") or b:IsA("Pants") or b:IsA("Shirt") or b:IsA("ShirtGraphic") or b:IsA("BodyColors") then
				b.Parent = newRig
			elseif b.Name == "Head" and b:FindFirstChild("face") then
				newRig.Head.face.Texture = b.face.Texture
			end
		end
		plr.Character = newRig
		newRig.Parent = workspace
		newRig.Head.CFrame = originalCFrame
		--local desc = main.players:GetHumanoidDescriptionFromUserId(plr.UserId)
		--newHumanoid:ApplyDescription(desc)
		main.signals.ChangeMainVariable:FireClient(plr, {"humanoidRigType", Enum.HumanoidRigType[rigType]})
	end
	--
end

function module:GetFakeName(plr)
	for a,b in pairs(plr.Character:GetChildren()) do
		if b:IsA("Model") and b:FindFirstChild("FakeHumanoid") then
			return b
		end
	end
end

function module:CreateFakeName(plr, name)
	local head = main:GetModule("cf"):GetHead(plr)
	if head then
		local fakeName = module:GetFakeName(plr)
		if not fakeName then
			fakeName = Instance.new("Model")
			local fakeHead = head:Clone()
			fakeHead.Name = "Head"
			fakeHead.Parent = fakeName
			fakeHead.face.Transparency = 1
			local weld = Instance.new("WeldConstraint")
			weld.Part0 = fakeHead
			weld.Part1 = head
			weld.Parent = fakeHead
			local fakeHumanoid = Instance.new("Humanoid")
			fakeHumanoid.Name = "FakeHumanoid"
			fakeHumanoid.Parent = fakeName
			fakeName.Parent = plr.Character
			head.Transparency = 1
		end
		if name then
			fakeName.Name = name
		end
	end
end

function module:RemoveEffect(plr, effectType)
	local effectName = "HDAdmin"..effectType
	if plr.Character then
		for a,b in pairs(plr.Character:GetDescendants()) do
			if b.Name == effectName then
				b:Destroy()
				break
			end
		end
	end
end

function module:CreateEffect(plr, effectType)
	local hrp = main:GetModule("cf"):GetHRP(plr)
	local targetParent = hrp
	if effectType == "ForceField" then
		targetParent = plr.Character
	end
	if hrp then
		local effectName = "HDAdmin"..effectType
		local effect = targetParent:FindFirstChild(effectName)
		if not effect then
			effect = Instance.new(effectType)
			effect.Name = effectName
			effect.Parent = targetParent
		end
	end
end

function module:UnFreeze(args)
	local plr = args[1]
	local itemName = "FreezeBlock"
	local item = main.pd[plr].Items[itemName]
	if item then
		main.pd[plr].Items[itemName] = nil
		main:GetModule("cf"):Movement(true, plr)
		main:GetModule("cf"):SetTransparency(plr.Character, 0)
		local head = main:GetModule("cf"):GetHead(plr)
		if head then
			head.CFrame = item.FreezeClone.Head.CFrame
		end
		local humanoid = main:GetModule("cf"):GetHumanoid(plr)
		if humanoid then
			main.signals.SetCameraSubject:FireClient(plr, (humanoid))
		end
		item:Destroy()
	end
end

function module:FilterString(text, fromPlayer, playerTo)
	local filteredText = ""
	local success, message = pcall(function()
		filteredText = main.chat:FilterStringAsync(text, fromPlayer, playerTo)
	end)
	if not success then
		filteredText = "####"
	end
	return filteredText
end

function module:FilterBroadcast(text, fromPlayer)
	local filteredText = ""
	local success, message = pcall(function()
		filteredText = main.chat:FilterStringForBroadcast(text, fromPlayer)
	end)
	if not success then
		filteredText = "####"
	end
	return filteredText
end

function module:DonorNotice(player, pdata)
	if not pdata.PromptedDonor then
		main:GetModule("PlayerData"):ChangeStat(player, "PromptedDonor", true)
		main:GetModule("cf"):FormatAndFireNotice(player, "WelcomeDonor")
	end
end

function module:CheckAndRankToDonor(player, pdata, gamepassId)
	gamepassId = tostring(gamepassId)
	if not pdata.Donor and (gamepassId == tostring(main.products.Donor) or gamepassId == tostring(main.products.OldDonor)) then
		main:GetModule("PlayerData"):ChangeStat(player, "Donor", true)
		module:DonorNotice(player, pdata)
	end
end

function module:Unrank(plr)
	main:GetModule("PlayerData"):ChangeStat(plr, "Rank", 0)
	main.serverAdmins[plr.Name] = nil
	main:GetModule("PlayerData"):ChangeStat(plr, "SaveRank", false)
	main:GetModule("cf"):FormatAndFireNotice(plr, "UnRank")
	return("Unranked")
end

function module:GetRankType(plr)
	local rankType = "Server"
	local pdata = main.pd[plr]
	if pdata then
		if pdata.AutomaticRank then
			rankType ="Auto"
		elseif pdata.SaveRank == true then
			rankType = "Perm"
		elseif main.serverAdmins[plr.Name] == nil then
			rankType = "Temp"
		end
	end
	return rankType
end

function module:SetRank(plr, speakerUserId, rankId, rankType)
	main:GetModule("PlayerData"):ChangeStat(plr, "Rank", rankId)
	main:GetModule("PlayerData"):ChangeStat(plr, "AutomaticRank", false)
	local stringRankType = "rank"
	if rankType == "Server" then
		main.serverAdmins[plr.Name] = true
	elseif rankType == "Perm" then
		main:GetModule("PlayerData"):ChangeStat(plr, "PermRankedBy", speakerUserId)
		main:GetModule("PlayerData"):ChangeStat(plr, "SaveRank", true)
		main.serverAdmins[plr.Name] = nil
		stringRankType = "permRank"
	elseif rankType == "Temp" then
		main.serverAdmins[plr.Name] = nil
		stringRankType = "tempRank"
	end
	local targetRankName = main:GetModule("cf"):GetRankName(rankId)
	main:GetModule("cf"):FormatAndFireNotice(plr, "SetRank", stringRankType, targetRankName)
end

function module:RankPlayerCommand(speaker, args, commandRankType)
	local plr = args[1]
	local targetRankId = args[2]
	local plrRank = main.pd[plr].Rank
	local speakerRank = main.pd[speaker].Rank
	if targetRankId == 0 then
		module:Unrank(plr)
		return("Unranked")
	elseif speakerRank > targetRankId then
		module:SetRank(plr, speaker.UserId, targetRankId, commandRankType)
		return("Ranked")
	end
end

function module:RankPlayerSimple(player, newRank, automaticRank)
	local pdata = main.pd[player]
	if tonumber(newRank) == nil then
		newRank = main:GetModule("cf"):GetRankId(newRank)
	end
	if pdata.Rank <= newRank then
		if automaticRank then
			main:GetModule("PlayerData"):ChangeStat(player, "AutomaticRank", newRank)
		end
		if pdata.Rank < newRank then
			main:GetModule("PlayerData"):ChangeStat(player, "Rank", newRank)
		end
	end
end



return module
