-- dangerous admin commands reserved for admin role or above

return {
	{
		name = "announce",
		description = "Shows a message to everyone in the game, saves and shows to new users until it has been cleared.",
		args = {
			{
				type = "string",
				name = "Message",
				description = "The message to send.",
			},
		},
		env = function(_K)
			task.spawn(_K.Util.Retry, function()
				_K.Service.Messaging:SubscribeAsync("KA_Announcement", function(message)
					if type(message.Data) == "string" then
						message.Data = _K.Service.Http:JSONDecode(message.Data)
					end
					if type(message.Data) ~= "table" then
						_K.Data.savedSettings.announcement = false
						return
					end

					local msg, from, duration = unpack(message.Data)
					_K.Data.savedSettings.announcement = message.Data
					_K.Remote.Announce:FireAll({
						From = from,
						Text = msg,
						Duration = duration or 0,
					})
				end)
			end, math.huge)
		end,

		run = function(context, message)
			if context._K.Data.SEPARATE_DATASTORE or context.global then
				return `Announcements are disabled in private servers.`
			end

			local announcement = { message, context.from }
			context._K.Data.savedSettings.announcement = announcement
			context._K.Data.Sync.settings.announcement = announcement
			task.spawn(context._K.Util.Retry, function()
				context._K.Service.Messaging:PublishAsync("KA_Announcement", announcement)
			end, math.huge)
			return
		end,
	},
	{
		name = "unannounce",
		aliases = { "clearannounce" },
		description = "Removes the pinned announcement.",
		args = {},

		run = function(context)
			if context._K.Data.SEPARATE_DATASTORE then
				return `Announcements are disabled in private servers.`
			end

			context._K.Data.savedSettings.announcement = false
			context._K.Data.Sync.settings.announcement = context._K.Data.REMOVE
			context._K.Service.Messaging:PublishAsync("KA_Announcement", nil)
			return
		end,
	},
	{
		name = "role",
		aliases = { "rank" },
		description = "Assigns a role(s) to one or more user(s).",
		args = {
			{
				type = "userIds",
				name = "Users(s)",
				description = "The user(s) to assign roles.",
			},
			{
				type = "roles",
				name = "Roles(s)",
				description = "The roles(s) to assign.",
			},
			{
				type = "boolean",
				name = "Temporary",
				description = "Assigns the role(s) only for the current server.",
				optional = true,
				permissions = { saveRoles = true },
			},
		},

		run = function(context, userIds, roles, temporary)
			local persist = if temporary or not context._K.Auth.hasPermission(context.from, "saveRoles")
				then false
				else true

			for _, userId in userIds do
				local rolesAdded = {}
				for _, role in roles do
					if context._K.Auth.userRoleAdd(userId, role, persist) then
						local roleData = context._K.Data.roles[role]
						table.insert(rolesAdded, `<b><font color="{roleData.color}">{roleData.name}</font></b>`)
					end
				end

				local player = context._K.Service.Players:GetPlayerByUserId(userId)
				if player and #rolesAdded > 0 then
					local prefix = context._K.getCommandPrefix(player.UserId)
					context._K.Remote.Notify:Fire(player, {
						Text = `Gave you the {table.concat(rolesAdded, ", ")} role{if #rolesAdded > 1 then "s" else ""}!\nSay <b>{prefix}cmds</b> or <b>{prefix}info</b> for details.`,
						From = context.from,
					})
				end
			end

			task.spawn(function()
				local roleString = {}
				for _, role in roles do
					local roleData = context._K.Data.roles[role]
					table.insert(roleString, `<b><font color="{roleData.color}">{roleData.name}</font></b>`)
				end

				local names = {}
				for _, userId in userIds do
					table.insert(names, context._K.Util.getUserInfo(userId).DisplayName)
				end

				context._K.Remote.Notify:Fire(context.fromPlayer, {
					From = "_K",
					Text = `Gave Roles: {table.concat(roleString, ", ")}\nTo: {table.concat(
						names,
						", "
					)}`,
				})
			end)
		end,
	},
	{
		name = "temprole",
		aliases = { "temprank" },
		description = "Assigns a temporary role(s) to one or more user(s).",
		args = {
			{
				type = "userIds",
				name = "Users(s)",
				description = "The user(s) to assign roles.",
			},
			{
				type = "roles",
				name = "Roles(s)",
				description = "The roles(s) to assign.",
			},
		},

		run = function(context, userIds, roles)
			for _, userId in userIds do
				local rolesAdded = {}
				for _, role in roles do
					if context._K.Auth.userRoleAdd(userId, role) then
						local roleData = context._K.Data.roles[role]
						table.insert(rolesAdded, `<b><font color="{roleData.color}">{roleData.name}</font></b>`)
					end
				end

				local player = context._K.Service.Players:GetPlayerByUserId(userId)
				if player and #rolesAdded > 0 then
					local prefix = context._K.getCommandPrefix(player.UserId)
					context._K.Remote.Notify:Fire(player, {
						Text = `Gave you the {table.concat(rolesAdded, ", ")} role{if #rolesAdded > 1 then "s" else ""}!\nSay <b>{prefix}cmds</b> or <b>{prefix}info</b> for details.`,
						From = context.from,
					})
				end
			end

			task.spawn(function()
				local roleString = {}
				for _, role in roles do
					local roleData = context._K.Data.roles[role]
					table.insert(roleString, `<b><font color="{roleData.color}">{roleData.name}</font></b>`)
				end

				local names = {}
				for _, userId in userIds do
					table.insert(names, context._K.Util.getUserInfo(userId).DisplayName)
				end

				context._K.Remote.Notify:Fire(context.fromPlayer, {
					From = "_K",
					Text = `Gave Roles: {table.concat(roleString, ", ")}\nTo: {table.concat(
						names,
						", "
					)}`,
				})
			end)
		end,
	},
	{
		name = "unrole",
		aliases = { "removerole", "unrank", "removerank" },
		description = "Removes one or more role(s) from one or more member(s).",
		args = {
			{
				type = "members",
				name = "Member(s)",
				description = "The member(s) to remove roles from.",
				lowerRank = true,
			},
			{
				type = "roles",
				name = "Roles(s)",
				description = "The roles(s) to remove.",
			},
		},

		run = function(context, members, roles)
			local membersUnroled = {}
			for _, userId in members do
				local member = context._K.Data.members[tostring(userId)]
				for _, role in roles do
					if context._K.Auth.userRoleRemove(userId, role) then
						table.insert(membersUnroled, member and member.name or userId)
					end
				end
			end

			if #membersUnroled == 0 then
				return
			end

			local roleString = {}
			for _, role in roles do
				local roleData = context._K.Data.roles[role]
				table.insert(roleString, `<b><font color="{roleData.color}">{roleData.name}</font></b>`)
			end
			context._K.Remote.Notify:Fire(context.fromPlayer, {
				Text = `Removed Roles: {table.concat(roleString, ", ")}\nFrom: {table.concat(
					membersUnroled,
					", "
				)}`,
			})
		end,
	},
	{
		name = "removemember",
		aliases = { "removepermissions", "removeroles" },
		description = "Removes all roles and permissions from one or more member(s).",
		args = {
			{
				type = "members",
				name = "Members(s)",
				description = "The member(s) to remove all roles and permissions from.",
				lowerRank = true,
				ignoreSelf = true,
			},
		},

		run = function(context, members)
			local membersUnroled = {}
			for _, userId in members do
				local key = tostring(userId)
				local member = context._K.Data.members[key]
				if member then
					context._K.Data.members[key] = nil
					context._K.Data.Sync.members[key] = context._K.Data.REMOVE
					context._K.Remote.Member:FireAll(key)
					table.insert(membersUnroled, member and member.name or key)
				end
			end

			if #membersUnroled == 0 then
				return
			end

			context._K.Remote.Notify:Fire(context.fromPlayer, {
				Text = `Removed member{#membersUnroled > 1 and "s" or ""}: {table.concat(
					membersUnroled,
					", "
				)}`,
			})
		end,
	},
	{
		name = "gear",
		description = "Gives one or more player(s) a gear.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to give the gear.",
			},
			{
				type = "integer",
				name = "AssetId",
				description = "The assetId of the gear.",
			},
		},

		run = function(context, players, assetId)
			local model = context._K.Service.Insert:LoadAsset(assetId)
			for _, child in model:GetChildren() do
				if child:IsA("BackpackItem") then
					local gear = child:Clone()
					for _, player in players do
						gear:Clone().Parent = player:FindFirstChild("Backpack") or player.Character
					end
				end
			end
			model:Destroy()
		end,
	},
	{
		name = "insert",
		aliases = { "ins" },
		description = "Inserts a model at the player's position.",
		args = {
			{
				type = "integer",
				name = "AssetId",
				description = "The assetId of the model.",
			},
		},

		env = function(_K)
			return {
				blocked = { 59524079, 59524162, 59524102, 59524044, 59524124, 59524006 },
			}
		end,
		run = function(context, assetId)
			if table.find(context.env.blocked, assetId) then
				return "Model has been blocked."
			end
			local ok, result = pcall(function()
				return context._K.Service.Insert:LoadAsset(assetId)
			end)
			if not ok then
				if string.find(result, "authorized") then
					return `{result} It must be added to the Game Creator's inventory!`
				else
					return result
				end
			end
			local packageRef = result:FindFirstChild("packageRef", true)
			if packageRef and packageRef:FindFirstChildOfClass("ObjectValue") then
				result:Destroy()
				return "Model has been blocked."
			end
			result.Parent = workspace
			result:MoveTo(context.fromPlayer.Character:GetPivot().Position)
			result:MakeJoints()
			table.insert(context._K.cleanupCommands, result)
			return
		end,
	},
	{
		name = "place",
		aliases = { "pl" },
		description = "Teleports one or more player(s) to a place.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to teleport to a place.",
				shouldRequest = true,
			},
			{
				type = "integer @ reservedServer",
				name = "PlaceId",
				description = "The identifier of the place or reserved server.",
			},
		},
		run = function(context, players, id)
			if type(id) == "number" then
				context._K.Util.SafeTeleport(id, players)
			else -- reservedServer
				local options = Instance.new("TeleportOptions")
				options.ReservedServerAccessCode = id[2]
				context._K.Util.SafeTeleport(id[3], players, options)
			end
			for _, player in players do
				context._K.Remote.Notify:Fire(player, {
					From = "_K",
					Text = "Teleport initiated...",
				})
			end
		end,
	},
	{
		name = "serverlock",
		aliases = { "slock" },
		description = "Locks the server preventing new players from joining.",
		args = {},
		run = function(context)
			if not context._K._serverLock then
				context._K._serverLock = context.fromPlayer.Name
				context._K.Remote.Notify:FireAll({
					Text = "The server has been locked.",
					From = context.from,
				})
			end
		end,
	},
	{
		name = "unserverlock",
		aliases = { "unslock" },
		description = "Unlocks the server allowing new players to join again.",
		args = {},
		run = function(context)
			context._K._serverLock = nil
			context._K.Remote.Notify:FireAll({
				Text = "The server has been unlocked.",
				From = context.from,
			})
		end,
	},
}


-- potentially abusive fun commands, moderator+ default

return {
	{
		name = "disco",
		aliases = { "🪩", "un🪩", "undisco" },
		description = "It's time to party! 🎉",
		env = function(_K)
			local env = { id = false, restore = false }
			function env.cleanup()
				if env.restore then
					_K.Service.Lighting.Ambient, _K.Service.Lighting.FogColor = unpack(env.restore)
					env.restore = false
				end
				env.id = false
			end
			return env
		end,

		run = function(context)
			if context.undo then
				return context.env.cleanup()
			end

			if not context.env.restore then
				context.env.restore = { context._K.Service.Lighting.Ambient, context._K.Service.Lighting.FogColor }
			end

			local t = time()
			context.env.id = t
			task.spawn(function()
				repeat
					local color = Color3.fromHSV((time() - t) % 1, 1, 1)
					context._K.Service.Lighting.Ambient = color
					context._K.Service.Lighting.FogColor = color
					task.wait(math.pi / 10)
				until context.env.id ~= t
			end)
			return
		end,
	},
	{
		name = "creeper",
		description = "Turns one or more player(s) into a creeper? Aww, man...",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to turn into a creeper.",
				shouldRequest = true,
			},
		},
		env = function(_K)
			return {
				apply = function(player)
					local character = player.Character
					local humanoid = character and character:FindFirstChildOfClass("Humanoid")
					if not (humanoid and character.PrimaryPart) or character:GetAttribute("_KCreeper") then
						return
					end

					local oldRigType = humanoid.RigType
					if humanoid.RigType == Enum.HumanoidRigType.R15 then
						character = _K.Registry.commands.r6.env.apply(player, Enum.HumanoidRigType.R6)
					end

					character:SetAttribute("_KCreeper", oldRigType)

					local torso = character:FindFirstChild("Torso")
					if not torso then
						return
					end

					torso.Transparency = 0

					local neck = torso:FindFirstChild("Neck")
					local rightShoulder = torso:FindFirstChild("Right Shoulder")
					local leftShoulder = torso:FindFirstChild("Left Shoulder")
					local rightHip = torso:FindFirstChild("Right Hip")
					local leftHip = torso:FindFirstChild("Left Hip")

					if neck then
						neck.C0 = CFrame.new(0, 1, 0) * CFrame.Angles(math.rad(90), math.rad(180), 0)
					end
					if rightShoulder then
						rightShoulder.C0 = CFrame.new(0, -1.5, -0.5) * CFrame.Angles(0, math.pi / 2, 0)
					end
					if leftShoulder then
						leftShoulder.C0 = CFrame.new(0, -1.5, -0.5) * CFrame.Angles(0, -math.pi / 2, 0)
					end
					if rightHip then
						rightHip.C0 = CFrame.new(0, -1, 0.5) * CFrame.Angles(0, math.pi / 2, 0)
					end
					if leftHip then
						leftHip.C0 = CFrame.new(0, -1, 0.5) * CFrame.Angles(0, -math.pi / 2, 0)
					end

					_K.Registry.commands.crm.env.update(
						character,
						Color3.new(0, 0.5, 0),
						0,
						Enum.Material.SmoothPlastic
					)
				end,
			}
		end,

		run = function(context, players: { Player })
			for _, player in players do
				context.env.apply(player)
			end
		end,
	},
	{
		name = "uncreeper",
		description = "Reverts one or more player(s) from a creeper",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to revert from a creeper.",
				shouldRequest = true,
			},
		},
		env = function(_K)
			return {
				apply = function(player)
					local character = player.Character
					local humanoid = character and character:FindFirstChildOfClass("Humanoid")
					local oldRigType = character and character:GetAttribute("_KCreeper")
					if not (humanoid and character.PrimaryPart) or not oldRigType then
						return
					end

					character:SetAttribute("_KCreeper", nil)

					if oldRigType == Enum.HumanoidRigType.R15 then
						_K.Registry.commands.r15.env.apply(player, Enum.HumanoidRigType.R15)
						return
					end

					local torso = character:FindFirstChild("Torso")
					if not torso then
						return
					end

					torso.Transparency = 0

					local neck = torso:FindFirstChild("Neck")
					local rightShoulder = torso:FindFirstChild("Right Shoulder")
					local leftShoulder = torso:FindFirstChild("Left Shoulder")
					local rightHip = torso:FindFirstChild("Right Hip")
					local leftHip = torso:FindFirstChild("Left Hip")

					if neck then
						neck.C0 = CFrame.new(0, 1, 0) * CFrame.Angles(math.rad(90), math.rad(180), 0)
					end
					if rightShoulder then
						rightShoulder.C0 = CFrame.new(1, 0.5, 0) * CFrame.Angles(0, math.rad(90), 0)
					end
					if leftShoulder then
						leftShoulder.C0 = CFrame.new(-1, 0.5, 0) * CFrame.Angles(0, math.rad(-90), 0)
					end
					if rightHip then
						rightHip.C0 = CFrame.new(1, -1, 0) * CFrame.Angles(0, math.rad(90), 0)
					end
					if leftHip then
						leftHip.C0 = CFrame.new(-1, -1, 0) * CFrame.Angles(0, math.rad(-90), 0)
					end

					_K.Registry.commands.crm.env.update(character)
				end,
			}
		end,

		run = function(context, players: { Player })
			for _, player in players do
				context.env.apply(player)
			end
		end,
	},
	{
		name = "dog",
		aliases = { "🐶", "🐎", "horse" },
		description = "Turns one or more player(s) into dog",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to turn into a dog.",
				shouldRequest = true,
			},
		},
		env = function(_K)
			return {
				R6 = function(character)
					if not (character and character.PrimaryPart) then
						return
					end

					local torso = character:FindFirstChild("Torso")
					if not torso then
						return
					end

					torso.Transparency = 1

					local neck = torso:FindFirstChild("Neck")
					local rightShoulder = torso:FindFirstChild("Right Shoulder")
					local leftShoulder = torso:FindFirstChild("Left Shoulder")
					local rightHip = torso:FindFirstChild("Right Hip")
					local leftHip = torso:FindFirstChild("Left Hip")

					if neck then
						neck.C0 = CFrame.new(0, -0.5, -2) * CFrame.Angles(math.rad(90), math.rad(180), 0)
					end
					if rightShoulder then
						rightShoulder.C0 = CFrame.new(0.5, -1.5, -1.5) * CFrame.Angles(0, math.pi / 2, 0)
					end
					if leftShoulder then
						leftShoulder.C0 = CFrame.new(-0.5, -1.5, -1.5) * CFrame.Angles(0, -math.pi / 2, 0)
					end
					if rightHip then
						rightHip.C0 = CFrame.new(1.5, -1, 1.5) * CFrame.Angles(0, math.pi / 2, 0)
					end
					if leftHip then
						leftHip.C0 = CFrame.new(-1.5, -1, 1.5) * CFrame.Angles(0, -math.pi / 2, 0)
					end

					local seat = _K.Flux.new "Seat" {
						Name = "_KDogSeat",
						Transparency = 0,
						Color = torso.Color,
						Material = torso.Material,
						CFrame = torso.CFrame,
						CastShadow = false,
						CanQuery = false,
						CanCollide = false,
						Massless = true,
						Size = Vector3.new(3, 1, 4),
						TopSurface = 0,
						BottomSurface = 0,
					}

					_K.Flux.new "Weld" {
						Parent = seat,
						Part0 = torso,
						Part1 = seat,
						C1 = CFrame.new(0, 0.5, 0),
					}

					seat.Parent = character
				end,
				R15 = function(character)
					if not (character and character.PrimaryPart) then
						return
					end

					local torso = character:FindFirstChild("UpperTorso")
					if not torso then
						return
					end

					local root = character:FindFirstChild("LowerTorso") and character.LowerTorso:FindFirstChild("Root")
					local neck = character:FindFirstChild("Head") and character.Head:FindFirstChild("Neck")
					local waist = character:FindFirstChild("UpperTorso")
						and character.UpperTorso:FindFirstChild("Waist")
					local rightShoulder = character:FindFirstChild("RightShoulder", true)
					local leftShoulder = character:FindFirstChild("LeftShoulder", true)
					local rightHip = character:FindFirstChild("RightHip", true)
					local leftHip = character:FindFirstChild("LeftHip", true)

					if root then
						root.C0 *= CFrame.Angles(-math.rad(60), 0, 0) - Vector3.new(0, 0.5, 0)
					end
					if waist then
						waist.C0 *= CFrame.Angles(-math.rad(30), 0, 0)
					end
					if neck then
						neck.C0 *= CFrame.Angles(math.pi / 2, 0, 0)
					end
					if rightShoulder then
						rightShoulder.C0 *= CFrame.Angles(math.pi / 4, 0, 0)
					end
					if leftShoulder then
						leftShoulder.C0 *= CFrame.Angles(math.pi / 4, 0, 0)
					end
					if rightHip then
						rightHip.C0 *= CFrame.Angles(-math.pi / 4, 0, 0)
					end
					if leftHip then
						leftHip.C0 *= CFrame.Angles(-math.pi / 4, 0, 0)
					end

					local seat = _K.Flux.new "Seat" {
						Name = "_KDogSeat",
						Transparency = 1,
						CastShadow = false,
						CanQuery = false,
						CanCollide = false,
						Massless = true,
						Size = Vector3.new(2, 1, 2),
						CFrame = torso.CFrame,
					}

					_K.Flux.new "Weld" {
						Parent = seat,
						Part0 = torso,
						Part1 = seat,
						C1 = CFrame.new(0, 0.1, -0.7) * CFrame.Angles(-math.pi / 2, 0, 0),
					}

					seat.Parent = character
				end,
			}
		end,

		run = function(context, players)
			for _, player in players do
				if
					player.Character
					and player.Character.PrimaryPart
					and player.Character:FindFirstChild("Humanoid")
					and not player.Character:FindFirstChild("_KDogSeat")
				then
					local humanoid = player.Character:FindFirstChild("Humanoid")
					if not humanoid then
						continue
					end

					if humanoid.RigType == Enum.HumanoidRigType.R6 then
						context.env.R6(player.Character)
					else
						context.env.R15(player.Character)
					end
				end
			end
		end,
	},
	{
		name = "undog",
		aliases = { "un🐶", "un🐎", "unhorse" },
		description = "Reverts one or more player(s) from dog",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to revert dog from.",
				shouldRequest = true,
			},
		},
		env = function(_K)
			return {
				R6 = function(character)
					if not (character and character.PrimaryPart) then
						return
					end

					local torso = character:FindFirstChild("Torso")
					if not torso then
						return
					end

					torso.Transparency = 0

					local neck = torso:FindFirstChild("Neck")
					local rightShoulder = torso:FindFirstChild("Right Shoulder")
					local leftShoulder = torso:FindFirstChild("Left Shoulder")
					local rightHip = torso:FindFirstChild("Right Hip")
					local leftHip = torso:FindFirstChild("Left Hip")

					if neck then
						neck.C0 = CFrame.new(0, 1, 0) * CFrame.Angles(math.rad(90), math.rad(180), 0)
					end
					if rightShoulder then
						rightShoulder.C0 = CFrame.new(1, 0.5, 0) * CFrame.Angles(0, math.rad(90), 0)
					end
					if leftShoulder then
						leftShoulder.C0 = CFrame.new(-1, 0.5, 0) * CFrame.Angles(0, math.rad(-90), 0)
					end
					if rightHip then
						rightHip.C0 = CFrame.new(1, -1, 0) * CFrame.Angles(0, math.rad(90), 0)
					end
					if leftHip then
						leftHip.C0 = CFrame.new(-1, -1, 0) * CFrame.Angles(0, math.rad(-90), 0)
					end
				end,
				R15 = function(character)
					if not (character and character.PrimaryPart) then
						return
					end

					local torso = character:FindFirstChild("UpperTorso")
					if not torso then
						return
					end

					local root = character:FindFirstChild("LowerTorso") and character.LowerTorso:FindFirstChild("Root")
					local neck = character:FindFirstChild("Head") and character.Head:FindFirstChild("Neck")
					local waist = character:FindFirstChild("UpperTorso")
						and character.UpperTorso:FindFirstChild("Waist")
					local rightShoulder = character:FindFirstChild("RightShoulder", true)
					local leftShoulder = character:FindFirstChild("LeftShoulder", true)
					local rightHip = character:FindFirstChild("RightHip", true)
					local leftHip = character:FindFirstChild("LeftHip", true)

					if root then
						root.C0 *= CFrame.Angles(math.rad(60), 0, 0) + Vector3.new(0, 0.5, 0)
					end
					if waist then
						waist.C0 *= CFrame.Angles(math.rad(30), 0, 0)
					end
					if neck then
						neck.C0 *= CFrame.Angles(-math.pi / 2, 0, 0)
					end
					if rightShoulder then
						rightShoulder.C0 *= CFrame.Angles(-math.pi / 4, 0, 0)
					end
					if leftShoulder then
						leftShoulder.C0 *= CFrame.Angles(-math.pi / 4, 0, 0)
					end
					if rightHip then
						rightHip.C0 *= CFrame.Angles(math.pi / 4, 0, 0)
					end
					if leftHip then
						leftHip.C0 *= CFrame.Angles(math.pi / 4, 0, 0)
					end
				end,
			}
		end,

		run = function(context, players, userId)
			for _, player in players do
				if not player.Character then
					continue
				end
				local seat = player.Character:FindFirstChild("_KDogSeat")
				if seat then
					seat:Destroy()
					local humanoid = player.Character:FindFirstChild("Humanoid")
					if not humanoid then
						continue
					end
					if humanoid.RigType == Enum.HumanoidRigType.R6 then
						context.env.R6(player.Character)
					else
						context.env.R15(player.Character)
					end
				end
			end
		end,
	},
	{
		name = "char",
		aliases = { "character" },
		description = "Changes the character of one or more player(s).",
		credit = { "Kohl @Scripth", "@AlanDev09" },
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) whose character to change.",
				shouldRequest = true,
			},
			{
				type = "userId",
				name = "UserId",
				description = "The identifier of the Roblox user.",
				optional = true,
			},
		},
		run = function(context, players, userId)
			local appearance = context._K.Service.Players:GetHumanoidDescriptionFromUserId(userId)
			if not appearance then
				return "Invalid character appearance!"
			end
			for _, player in players do
				player.CharacterAppearanceId = if userId == nil then player.UserId else userId
				local humanoid = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
				if not humanoid then
					continue
				end
				local oldDescription = player:FindFirstChild("_KHumanoidDescription")
				if oldDescription then
					oldDescription:Destroy()
				end
				task.spawn(humanoid.ApplyDescription, humanoid, appearance)
			end
			return
		end,
	},
	{
		name = "unchar",
		aliases = { "uncharacter" },
		description = "Restores the character of one or more player(s).",
		credit = { "Kohl @Scripth", "@AlanDev09" },
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) whose character to restore.",
			},
		},
		env = function(_K)
			return {
				apply = function(player, humanoid)
					local appearance = _K.Service.Players:GetHumanoidDescriptionFromUserId(player.UserId)
					if appearance then
						humanoid:ApplyDescription(appearance)
					end
				end,
			}
		end,
		run = function(context, players)
			for _, player in players do
				if player.CharacterAppearanceId == player.UserId then
					continue
				end
				player.CharacterAppearanceId = player.UserId
				local humanoid = player.Character:FindFirstChildOfClass("Humanoid")
				if not humanoid then
					continue
				end
				local oldDescription = player:FindFirstChild("_KHumanoidDescription")
				if oldDescription then
					oldDescription:Destroy()
				end
				task.spawn(context.env.apply, player, humanoid)
			end
		end,
	},
	{
		name = "clone",
		aliases = {},
		description = "Clones the character of one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) whose character to clone.",
			},
		},

		run = function(context, players, userId)
			for _, player in players do
				if player.Character then
					player.Character.Archivable = true
					local clone = player.Character:Clone()
					player.Character.Archivable = false
					clone.Name ..= "Clone"
					clone.Parent = workspace
					table.insert(context._K.cleanupCommands, clone)
					clone:MoveTo(player.Character:GetPivot().Position)
				end
			end
		end,
	},
	{
		name = "control",
		aliases = { "takeover" },
		description = "Controls the character of a player.",
		args = {
			{
				type = "player",
				name = "Player",
				description = "The player to control.",
				shouldRequest = true,
				ignoreSelf = true,
			},
		},
		envClient = function(_K)
			_K.Remote.ControlCommand:Connect(function(target: Humanoid | Model)
				if target then
					workspace.CurrentCamera.CameraSubject = target
				end
			end)
		end,
		env = function(_K)
			return {
				connections = {},
				remote = _K.Remote.ControlCommand,
			}
		end,
		run = function(context, player: Player)
			local character = player and player.Character
			if not character then
				return `{player} doesn't have a character!`
			end
			local humanoid = character:FindFirstChildOfClass("Humanoid")
			if not humanoid then
				return `{player} doesn't have a humanoid!`
			end

			context.fromPlayer.Character = character
			context.env.remote:Fire(context.fromPlayer, humanoid)
			context.env.remote:Fire(player, humanoid)

			for _, descendant in character:GetDescendants() do
				if descendant:IsA("BasePart") and descendant:CanSetNetworkOwnership() then
					descendant:SetNetworkOwner(context.fromPlayer)
				end
			end

			if not context.env.connections[player] then
				context.env.connections[player] = context.fromPlayer
					:GetPropertyChangedSignal("Character")
					:Once(function()
						context.env.connections[player] = nil
						if player and player.Parent and humanoid and humanoid.Health > 0 then
							local old = character:GetPivot()
							player:LoadCharacterAsync()
							local newCharacter = player.Character
							newCharacter:PivotTo(old)
							context._K.Remote.Refresh:Fire(player)
						end
					end)
			end

			return
		end,
	},
	{
		name = "jumpscare",
		aliases = { "js" },
		credit = { "Kohl @Scripth", "Pok @vonials" },
		description = "Jumpscares a player with an image and sound.",
		group = "Fun",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) whose performance to improve.",
				shouldRequest = true,
			},
			{
				type = "image",
				name = "DecalId",
				description = "The image to show the player(s).",
				optional = true,
			},
			{
				type = "number",
				name = "SoundId",
				description = "The sound to play.",
				optional = true,
			},
		},
		envClient = function(_K)
			_K.Remote.Jumpscare:Connect(function(imageId: string, soundId: number)
				local image = _K.UI.new "ImageLabel" {
					Name = "JumpScare",
					Parent = _K.UI.LayerTop,
					BackgroundTransparency = 0,
					BackgroundColor3 = Color3.new(0, 0, 0),
					Size = UDim2.fromScale(1, 1),
					Image = imageId,
					ZIndex = 9e8,
				}
				local sound = _K.UI.new "Sound" {
					Parent = image,
					SoundId = "rbxassetid://" .. (tonumber(soundId) or 0),
					Volume = 5,
				}
				sound:Play()
				task.delay(2, game.Destroy, image)
			end)
		end,
		env = function(_K)
			return { remote = _K.Remote.Jumpscare }
		end,
		run = function(context, players: { Players }, decalId: string?, soundId: number?)
			decalId = decalId or "rbxassetid://1119705746"
			soundId = soundId or 130285917830946

			for _, player in players do
				context.env.remote:Fire(player, decalId, soundId)
			end
		end,
	},
	{
		name = "glitch",
		aliases = { "unglitch", "vibrate", "unvibrate" },
		description = "Makes one or more player(s) start glitching.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to glitch.",
				shouldRequest = true,
			},
			{
				type = "number",
				name = "Distance",
				description = "The glitch distance.",
				optional = true,
			},
		},

		envClient = function(_K)
			local connection
			_K.Remote.Glitch:Connect(function(enable: boolean?, distance: number?)
				if connection then
					connection:Disconnect()
				end
				local character = _K.LocalPlayer.Character
				if enable and character then
					local d = distance or 1
					local switch = false
					connection = _K.Service.RunService.preRender:Connect(function()
						switch = not switch
						character:PivotTo(character:GetPivot() * CFrame.new(0, 0, if switch then -d else d))
					end)
				end
			end)
		end,
		env = function(_K)
			return {
				remote = _K.Remote.Glitch,
			}
		end,
		run = function(context, players: { Player }, distance: number)
			for _, player in players do
				context.env.remote:Fire(player, not context.undo, distance)
			end
		end,
	},
	{
		name = "seizure",
		aliases = { "seize" },
		description = "Makes one or more player(s) start seizing.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to seize.",
				shouldRequest = true,
			},
		},

		env = function(_K)
			return {
				apply = function(character: Model)
					if character:GetAttribute("_KSeizure") then
						return
					end
					character:SetAttribute("_KSeizure", true)
					character:PivotTo(character:GetPivot() * CFrame.Angles(math.pi / 2, 0, 0))
					local humanoid = character:FindFirstChildOfClass("Humanoid")
					while
						character
						and character.Parent
						and character.PrimaryPart
						and humanoid
						and character:GetAttribute("_KSeizure")
					do
						humanoid.PlatformStand = true
						character.PrimaryPart.AssemblyLinearVelocity =
							Vector3.new(math.random(-10, 10), math.random(-5, 1), math.random(-10, 10))
						character.PrimaryPart.AssemblyAngularVelocity =
							Vector3.new(math.random(-5, 5), math.random(-5, 5), math.random(-5, 5))
						task.wait()
					end
					if humanoid then
						humanoid.PlatformStand = false
					end
				end,
			}
		end,
		run = function(context, players: { Player })
			for _, player in players do
				if player.Character then
					context.env.apply(player.Character)
				end
			end
		end,
	},
	{
		name = "unseizure",
		aliases = { "unseize" },
		description = "Saves one or more player(s) from seizing.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to save.",
				shouldRequest = true,
			},
		},

		run = function(context, players: { Player })
			for _, player in players do
				if player.Character then
					player.Character:SetAttribute("_KSeizure", nil)
				end
			end
		end,
	},
	{
		name = "infect",
		aliases = { "zombie" },
		description = "Infects of one or more player(s), starting a zombie outbreak!",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to infect.",
				shouldRequest = true,
			},
		},
		env = function(_K)
			local env = { infected = {} }

			function env.infect(player, character)
				if not character then
					return
				end
				local humanoid = character:FindFirstChildOfClass("Humanoid")
				if not humanoid then
					return
				end

				local face = character:FindFirstChild("Head") and character.Head:FindFirstChild("face")
				if face then
					if not face:GetAttribute("_KInfectOriginal") then
						face:SetAttribute("_KInfectOriginal", face.Texture)
					end
					face.Texture = "rbxassetid://629946036"
				end

				local colors = character:FindFirstChildOfClass("BodyColors")
				if colors then
					colors.HeadColor3 = Color3.fromRGB(50, 100, 50)
					colors.LeftArmColor3 = Color3.fromRGB(50, 100, 50)
					colors.RightArmColor3 = Color3.fromRGB(50, 100, 50)
					colors.TorsoColor3 = Color3.fromRGB(100, 50, 20)
					colors.LeftLegColor3 = Color3.fromRGB(100, 50, 20)
					colors.RightLegColor3 = Color3.fromRGB(100, 50, 20)
				end

				local shirt = character:FindFirstChildOfClass("Shirt")
				if shirt then
					shirt:Destroy()
				end

				local pants = character:FindFirstChildOfClass("Pants")
				if pants then
					pants:Destroy()
				end

				_K.Flux
					.new "Sound" {
					Parent = character.PrimaryPart,
					PlayOnRemove = true,
					SoundId = "rbxassetid://9114030073",
				}
					:Destroy()

				env.infected[character] = humanoid.Touched:Connect(function(part)
					if not part or not part.Parent or env.infected[part.Parent] then
						return
					end

					local player = _K.Service.Players:GetPlayerFromCharacter(part.Parent)
					if not player then
						return
					end

					env.infect(player, part.Parent)
				end)

				player.CharacterRemoving:Once(function()
					if env.infected[character] then
						env.infected[character]:Disconnect()
						env.infected[character] = nil
					end
				end)
			end

			return env
		end,

		run = function(context, players)
			for _, player in players do
				context.env.infect(player, player.Character)
			end
		end,
	},

	{
		name = "explode",
		aliases = { "boom", "💥" },
		description = "Explodes one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to explode.",
				shouldRequest = true,
			},
		},
		run = function(context, players, distance)
			for _, player in players do
				if player.Character then
					local humanoid = player.Character:FindFirstChildOfClass("Humanoid")
					if not humanoid then
						continue
					end

					humanoid.MaxHealth = math.max(1, humanoid.MaxHealth)
					humanoid.Health = 0

					local explosion = Instance.new("Explosion")
					explosion.ExplosionType = Enum.ExplosionType.NoCraters
					explosion.Position = player.Character:GetPivot().Position
					explosion.DestroyJointRadiusPercent = 0
					explosion.Parent = player.Character
				end
			end
		end,
	},
	{
		name = "nuke",
		aliases = {},
		description = "Nuke one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to nuke.",
				shouldRequest = true,
			},
		},
		env = function(_K)
			local boomSound = _K.Flux.new "Sound" {
				SoundId = "rbxassetid://9114224354",
				EmitterSize = 512,
				Volume = 1,
			}
			local sphere
			task.defer(function()
				local ok, result = _K.Util.Retry(function()
					return _K.Service.Insert:CreateMeshPartAsync(
						"rbxassetid://116325731356319",
						Enum.CollisionFidelity.Box,
						Enum.RenderFidelity.Precise
					)
				end)
				if not ok then
					sphere = Instance.new("MeshPart")
					return
				end
				sphere = result

				_K.Flux.edit(sphere, {
					Name = "Sphere",
					Color = Color3.new(1, 0, 0),
					Material = Enum.Material.Neon,
					Transparency = 0.75,
					Anchored = true,
					EnableFluidForces = false,
					CastShadow = false,
					CanCollide = false,
					CanTouch = false,
					CanQuery = false,
					Massless = true,
					Size = Vector3.zero,
				})
			end)

			local function explode(character, position)
				if character:GetAttribute("_KNuked") then
					return
				end
				character:SetAttribute("_KNuked", true)

				local explosion = Instance.new("Explosion")
				explosion.ExplosionType = Enum.ExplosionType.NoCraters
				explosion.Position = position
				explosion.DestroyJointRadiusPercent = 0
				explosion.Parent = character

				local humanoid = character:FindFirstChildOfClass("Humanoid")
				if not humanoid then
					return
				end

				humanoid.MaxHealth = math.max(1, humanoid.MaxHealth)
				humanoid.Health = 0
			end

			return {
				explode = explode,
				nuke = function(from: Player?, fromRank, position)
					local part = sphere:Clone()
					part.Position = position

					local part2 = sphere:Clone()
					part2.Color = Color3.new(1, 1, 0)
					part2.Position = position + Vector3.new(0, 0.1, 0)
					part2.Parent = part

					local part3 = sphere:Clone()
					part3.Color = Color3.new(1, 1, 1)
					part3.Position = position - Vector3.new(0, 0.1, 0)
					part3.Parent = part

					part.Parent = workspace

					local sound = boomSound:Clone()
					sound.Parent = part
					sound:Play()
					task.delay(2, function()
						local sound = boomSound:Clone()
						sound.Volume = 1
						sound.Parent = part
						sound:Play()
					end)

					local start, alpha = tick(), 0
					repeat
						alpha = _K.Service.Tween:GetValue(
							1 - (1 - math.clamp((tick() + 1 - start) / 8, 0, 1)) ^ 2,
							Enum.EasingStyle.Bounce,
							Enum.EasingDirection.In
						)
						local distance = alpha * 512
						part.Size = Vector3.one * distance
						part2.Size = part.Size * 0.9
						part3.Size = part.Size * 0.5
						for _, player in _K.Service.Players:GetPlayers() do
							if
								(not from or from.UserId ~= _K.creatorId)
								and _K.Auth.getRank(player.UserId) >= fromRank
							then
								continue
							end
							local direction = (player.Character and not player.Character:GetAttribute("_KNuked"))
								and position - player.Character:GetPivot().Position
							if direction and direction.Magnitude <= distance / 2 then
								explode(player.Character, player.Character:GetPivot().Position + direction.unit)
							end
						end
						task.wait()
					until alpha == 1

					start, alpha = tick(), 0
					repeat
						alpha = _K.Service.Tween:GetValue(
							math.clamp((tick() - start) / 1, 0, 1),
							Enum.EasingStyle.Cubic,
							Enum.EasingDirection.In
						)
						local distance = 512 - 512 * alpha
						part.Transparency = 0.75 + 0.25 * alpha
						part2.Transparency = part.Transparency
						part3.Transparency = part.Transparency
						part.Size = Vector3.one * distance
						part2.Size = part.Size * 0.9
						part3.Size = part.Size * 0.5
						task.wait()
					until alpha == 1

					task.wait(4)
					part:Destroy()
				end,
			}
		end,
		run = function(context, players)
			for _, player in players do
				if player.Character then
					local position = player.Character:GetPivot().Position
					context.env.explode(player.Character, position)
					task.spawn(context.env.nuke, context.fromPlayer, context.fromRank, position)
				end
			end
		end,
	},
	{
		name = "smite",
		credit = { "@Yuruzuu", "Kohl @Scripth" },
		description = "Smites one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to smite.",
				shouldRequest = true,
			},
		},
		run = function(context, players)
			for _, player in players do
				if player.Character then
					local root = player.Character:FindFirstChild("HumanoidRootPart") or player.Character.PrimaryPart
					local humanoid = player.Character:FindFirstChildOfClass("Humanoid")
					if not (humanoid and root) then
						continue
					end

					for _, descendant in player.Character:GetDescendants() do
						if descendant:IsA("BasePart") then
							task.delay(math.random(), function()
								local effect = context._K.Flux.new "ParticleEmitter" {
									Parent = descendant,
									LockedToPart = true,
									Brightness = 4,
									Color = ColorSequence.new(Color3.new(1, 1, 0.5)),
									Transparency = NumberSequence.new(0.5),
									LightEmission = 1,
									LightInfluence = 0,
									Orientation = Enum.ParticleOrientation.FacingCamera,
									Texture = "rbxassetid://11492870634",
									ZOffset = 2,
									Lifetime = NumberRange.new(0.5, 0.75),
									Rate = 2,
									Speed = NumberRange.new(0),
									Rotation = NumberRange.new(-360, 360),
									FlipbookLayout = Enum.ParticleFlipbookLayout.Grid4x4,
									FlipbookMode = Enum.ParticleFlipbookMode.OneShot,
								}
								effect:Emit(1)
							end)
						end
					end

					local sounds = { 9116282544, 9116282647, 9116282646, 9116282791, 9116282875 }
					local sound = context._K.Flux.new "Sound" {
						Parent = workspace,
						SoundId = `rbxassetid://{sounds[math.random(4)]}`,
						PlayOnRemove = true,
						Volume = 1,
					}
					sound:Destroy()

					local hipHeight = if humanoid.RigType == Enum.HumanoidRigType.R15
						then humanoid.HipHeight + root.Size.Y / 2
						else root.Size.Y * 1.5

					task.delay(2.2, function()
						local part = context._K.Flux.new "Part" {
							Parent = workspace,
							Transparency = 0.9,
							Material = Enum.Material.Neon,
							Color = Color3.new(1, 1, 1),
							Anchored = true,
							CanCollide = false,
							CanQuery = false,
							CanTouch = false,
							CastShadow = false,
							Size = Vector3.one,
							CFrame = CFrame.new(player.Character:GetPivot().Position - Vector3.new(0, hipHeight, 0)),

							context._K.Flux.new "BlockMesh" {
								Scale = Vector3.new(2, 1e4, 2),
								Offset = Vector3.new(0, 5e3, 0),
							},
						}

						for i = 1, 4 do
							local outer = part:Clone()
							outer.Mesh.Scale = Vector3.new(2 + i, 1e4, 2 + i)
							outer.Parent = part
						end

						humanoid.MaxHealth = math.max(1, humanoid.MaxHealth)
						humanoid.Health = 0
						task.delay(0.4, part.Destroy, part)
					end)
				end
			end
		end,
	},
	{
		name = "confuse",
		aliases = { "reverse", "unconfuse", "unreverse" },
		description = "Inverts the controls of one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to confuse.",
				shouldRequest = true,
			},
		},
		envClient = function(_K)
			task.spawn(function()
				local function invertControls(player, direction, relative)
					player.Move(player, -direction, relative)
				end
				_K.Remote.Confuse:Connect(function(enable)
					local player = _K.Service.Players.LocalPlayer
					local playerScripts = player:WaitForChild("PlayerScripts")
					local playerModule = require(playerScripts:WaitForChild("PlayerModule"))
					playerModule:GetControls().moveFunction = if enable then invertControls else player.Move
				end)
			end)
		end,
		env = function(_K)
			return {
				remote = _K.Remote.Confuse,
			}
		end,

		run = function(context, players)
			for _, player in players do
				context.env.remote:Fire(player, not context.undo)
			end
		end,
	},
	{
		name = "fling",
		aliases = {},
		description = "Flings one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to fling.",
				shouldRequest = true,
			},
			{
				type = "number",
				name = "Strength",
				description = "The strength of the fling, 1 is default.",
				optional = true,
			},
		},
		env = function(_K)
			return {
				apply = function(character, strength)
					local angularStrength = strength * 10
					if character and character:FindFirstChild("HumanoidRootPart") then
						character:PivotTo(character:GetPivot() * CFrame.Angles(math.pi, 0, 0))

						local direction = CFrame.Angles(0, math.random() * math.pi * 2, 0).LookVector
						character.HumanoidRootPart.AssemblyLinearVelocity = direction
								* math.random(strength * 160, strength * 200)
							+ Vector3.new(0, math.random(strength * 160, strength * 200), 0)

						character.HumanoidRootPart.AssemblyAngularVelocity = Vector3.new(
							math.random(-angularStrength, angularStrength),
							math.random(-angularStrength, angularStrength),
							math.random(-angularStrength, angularStrength)
						)
					end
				end,
			}
		end,
		run = function(context, players: { Player }, strength: number?)
			for _, player in players do
				context.env.apply(player.Character, strength or 1)
			end
		end,
	},
	{
		name = "loopfling",
		aliases = { "unloopfling" },
		description = "Flings one or more player(s) repeatedly.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to fling repeatedly.",
				shouldRequest = true,
			},
			{
				type = "number",
				name = "Strength",
				description = "The strength of the fling, 1 is default.",
				optional = true,
			},
		},
		env = function(_K)
			local flinging = {}
			task.spawn(function()
				repeat
					for userId, strength in flinging do
						local player = _K.Service.Players:GetPlayerByUserId(userId)
						if not (player and player.Character) then
							continue
						end
						_K.Registry.commands.fling.env.apply(player.Character, strength)
					end
					task.wait(2)
				until _K.Data.gameClosing
			end)
			return { flinging = flinging }
		end,
		run = function(context, players: { Player }, strength: number?)
			for _, player in players do
				context.env.flinging[player.UserId] = if context.undo then nil else (strength or 1)
			end
		end,
	},
	{
		name = "poison",
		description = "Damages one or more player(s) over time.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to poison.",
				shouldRequest = true,
			},
			{
				type = "number",
				name = "Damage",
				description = "The damage to deal to their health.",
			},
			{
				type = "number",
				name = "Duration",
				description = "The duration of the poison effect in seconds, defaults to 8.",
				optional = true,
			},
		},

		env = function(_K)
			local function removeEffect(effect: Smoke)
				effect.Enabled = false
				task.wait(5)
				effect:Destroy()
			end
			return {
				apply = function(humanoid: Humanoid, damage: number, duration: number?)
					local effect = Instance.new("Smoke")
					effect.Name = "_KPoisonEffect"
					effect.Color = Color3.new(0.5, 0, 1)
					effect.Opacity = 0.1
					effect.RiseVelocity = 0
					effect.Parent = humanoid.RootPart
					task.delay(math.clamp(duration or 8, 0, 999), removeEffect, effect)
					local dealt = 0
					repeat
						local hit = math.min(damage / (duration or 8) * task.wait(0.8), damage - dealt)
						dealt += hit
						humanoid:TakeDamage(hit)
					until dealt >= damage
				end,
			}
		end,
		run = function(context, players, damage, duration)
			for _, player in players do
				local humanoid = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
				if humanoid then
					task.spawn(context.env.apply, humanoid, damage, duration)
				end
			end
		end,
	},
	{
		name = "spin",
		aliases = {},
		description = "Spins one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to spin.",
				shouldRequest = true,
			},
			{
				type = "number",
				name = "Speed",
				description = "The speed of the spin, 1 is default.",
				optional = true,
			},
		},

		run = function(context, players, speed)
			speed = Vector3.new(0, 30 * (speed or 1))

			for _, player in players do
				if
					player.Character
					and player.Character.PrimaryPart
					and player.Character.PrimaryPart:FindFirstChildOfClass("Attachment")
				then
					local existing = player.Character:FindFirstChild("_KSpin")
					if existing then
						existing:Destroy()
					end

					local angular = Instance.new("AngularVelocity")
					angular.Name = "_KSpin"
					angular.Attachment0 = player.Character.PrimaryPart:FindFirstChildOfClass("Attachment")
					angular.AngularVelocity = speed
					angular.MaxTorque = math.huge
					angular.Parent = player.Character
				end
			end
		end,
	},
	{
		name = "unspin",
		aliases = {},
		description = "Stops spinning one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to stop spinning.",
			},
		},

		run = function(context, players)
			for _, player in players do
				if player.Character then
					local existing = player.Character:FindFirstChild("_KSpin")
					if existing then
						existing:Destroy()
					end
				end
			end
		end,
	},
	{
		name = "setgravity",
		aliases = { "setgrav", "grav", "nograv", "ungravity", "ungrav", "resetgravity", "resetgrav" },
		description = "Sets the gravity of one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) whose gravity to change.",
				shouldRequest = true,
			},
			{
				type = "number",
				name = "Strength",
				description = "The gravity strength, default is 1.",
				optional = true,
			},
		},
		env = function(_K)
			return { resetAlias = { "ungravity", "ungrav", "resetgravity", "resetgrav" } }
		end,

		run = function(context, players, strength)
			strength = strength or 1
			if context.alias == "nograv" then
				strength = -1
			elseif table.find(context.env.resetAlias, context.alias) then
				strength = 1
			end

			for _, player in players do
				if
					player.Character
					and player.Character.PrimaryPart
					and player.Character.PrimaryPart:FindFirstChildOfClass("Attachment")
				then
					local existing = player.Character:FindFirstChild("_KGravityForce")
					if existing then
						existing:Destroy()
					end
					if strength == 1 then
						continue
					end

					local force = Instance.new("VectorForce")
					force.Name = "_KGravityForce"
					force.ApplyAtCenterOfMass = true
					force.Attachment0 = player.Character.PrimaryPart:FindFirstChildOfClass("Attachment")
					force.RelativeTo = Enum.ActuatorRelativeTo.World
					force.Force =
						Vector3.new(0, player.Character.PrimaryPart.AssemblyMass * -strength * workspace.Gravity)
					force.Parent = player.Character
				end
			end
		end,
	},
	{
		name = "skydive",
		aliases = { "freefall" },
		description = "Sends one or more player(s) into the sky.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to send into the sky.",
				shouldRequest = true,
			},
			{
				type = "number",
				name = "Distance",
				description = "The distance, in studs, that players are sent into the sky.",
				optional = true,
			},
		},
		run = function(context, players, distance)
			for _, player in players do
				if player.Character then
					player.Character:TranslateBy(Vector3.new(0, distance or 8e3, 0))
				end
			end
		end,
	},
	{
		name = "trip",
		aliases = {},
		description = "Trips one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to trip.",
				shouldRequest = true,
			},
		},
		envClient = function(_K)
			_K.Remote.Trip:Connect(function()
				local character = _K.LocalPlayer.Character
				local humanoid = character and character:FindFirstChildOfClass("Humanoid")
				if humanoid then
					humanoid:ChangeState(Enum.HumanoidStateType.FallingDown)

					local direction = CFrame.Angles(0, math.random() * math.pi * 2, 0).LookVector
					character.PrimaryPart.AssemblyAngularVelocity = direction * 8
				end
			end)
			return true
		end,
		env = function(_K)
			return {
				remote = _K.Remote.Trip,
			}
		end,

		run = function(context, players)
			for _, player in players do
				context.env.remote:Fire(player)
			end
		end,
	},
	{
		name = "rocket",
		aliases = { "🚀" },
		description = "Attaches a rocket to one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to attach a rocket to.",
				shouldRequest = true,
			},
		},

		run = function(context, players, speed)
			for _, player in players do
				if
					player.Character
					and player.Character.PrimaryPart
					and player.Character:FindFirstChildOfClass("Humanoid")
				then
					local existing = player.Character:FindFirstChild("_KRocket")
					if existing then
						continue
					end

					player.Character:FindFirstChildOfClass("Humanoid").Jump = true

					local attachment = Instance.new("Attachment")
					attachment.Position = Vector3.new(0, -3, 0)
					context._K.Flux.new "Fire" {
						Parent = attachment,
						Size = 2,
					}

					local rocket = context._K.Flux.new "Part" {
						Parent = player.Character,
						Name = "_KRocket",
						Size = Vector3.new(1, 6, 1),
						Anchored = false,
						CanCollide = false,
						Massless = true,
						TopSurface = 0,
						BottomSurface = 0,
						Material = Enum.Material.Metal,

						attachment,
						context._K.Flux.new "VectorForce" {
							ApplyAtCenterOfMass = true,
							RelativeTo = Enum.ActuatorRelativeTo.World,
							Force = Vector3.new(0, player.Character.PrimaryPart.AssemblyMass * workspace.Gravity + 800),
							Attachment0 = attachment,
						},
					}

					context._K.Flux.new "Weld" {
						Parent = rocket,
						Part0 = rocket,
						Part1 = player.Character.PrimaryPart,
						C1 = CFrame.new(0, 0, 1),
					}

					task.delay(5, function()
						if player.Character then
							player.Character:BreakJoints()
							rocket:Destroy()
							local explosion = Instance.new("Explosion")
							explosion.ExplosionType = Enum.ExplosionType.NoCraters
							explosion.Position = rocket.Position
							explosion.DestroyJointRadiusPercent = 0
							explosion.Parent = player.Character
						end
					end)
				end
			end
		end,
	},

	{
		name = "size",
		aliases = { "resize", "scale", "unsize", "unresize", "unscale" },
		description = "Resizes one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to resize.",
				shouldRequest = true,
			},
			{
				type = "number",
				name = "Scale",
				description = "The scale of the character, 1 is default.",
				optional = true,
			},
		},

		run = function(context, players, scale)
			for _, player in players do
				player.Character:ScaleTo(math.clamp(scale, 0.01, 50) or 1)
			end
		end,
	},
	{
		name = "slim",
		aliases = { "unslim" },
		description = "Makes one or more player(s) slim.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to make slim.",
				shouldRequest = true,
			},
		},
		env = function(_K)
			return {
				slim = function(object, property, undo)
					local originalValue = object:GetAttribute("_KSlimOriginal")
					if undo or not originalValue then
						object:SetAttribute("_KSlimOriginal", if undo then nil else object[property].Z)
					end
					local value = object[property]
					object[property] = Vector3.new(value.X, value.Y, if undo then originalValue or value else 0.2)
				end,
			}
		end,

		run = function(context, players)
			for _, player in players do
				local character = player.Character
				local humanoid = character and character:FindFirstChildOfClass("Humanoid")
				if not humanoid or (context.undo and not humanoid:GetAttribute("_KSlim")) then
					continue
				end
				humanoid:SetAttribute("_KSlim", not context.undo)
				for _, object in character:GetChildren() do
					if object:IsA("BasePart") then
						context.env.slim(object, "Size", context.undo)
					elseif object:IsA("Accessory") then
						local part = object:FindFirstChildWhichIsA("BasePart")
						if part then
							context.env.slim(part, "Size", context.undo)
							local mesh = part:FindFirstChildOfClass("SpecialMesh")
							if mesh then
								context.env.slim(mesh, "Scale", context.undo)
							end
						end
					end
				end
			end
		end,
	},
	{
		name = "noobify",
		aliases = { "noob" },
		description = "Turn one or more player(s) into a noob",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to transform into a noob.",
				shouldRequest = true,
			},
		},
		env = function(_K)
			local blue = BrickColor.new("Bright blue").Color
			local green = BrickColor.new("Br. yellowish green").Color
			local yellow = BrickColor.new("Bright yellow").Color

			return {
				properties = {
					HeadColor = yellow,
					LeftArmColor = yellow,
					RightArmColor = yellow,
					LeftLegColor = green,
					RightLegColor = green,
					TorsoColor = blue,
					Pants = 0,
					Shirt = 0,
					GraphicTShirt = 0,
					LeftArm = 0,
					RightArm = 0,
					LeftLeg = 0,
					RightLeg = 0,
					Torso = 0,
				},
				accessoryColors = {
					[Enum.AccessoryType.Hat] = yellow,
					[Enum.AccessoryType.Hair] = yellow,
					[Enum.AccessoryType.Face] = blue,
					[Enum.AccessoryType.Neck] = blue,
					[Enum.AccessoryType.Shoulder] = blue,
					[Enum.AccessoryType.Front] = blue,
					[Enum.AccessoryType.Back] = blue,
					[Enum.AccessoryType.Waist] = blue,
					[Enum.AccessoryType.TShirt] = blue,
					[Enum.AccessoryType.Shirt] = blue,
					[Enum.AccessoryType.Pants] = green,
					[Enum.AccessoryType.Jacket] = blue,
					[Enum.AccessoryType.Sweater] = blue,
					[Enum.AccessoryType.Shorts] = green,
					[Enum.AccessoryType.LeftShoe] = green,
					[Enum.AccessoryType.RightShoe] = green,
					[Enum.AccessoryType.DressSkirt] = blue,
				},
				fallback = yellow,
				getDescription = function(player: Player, humanoid: Humanoid): HumanoidDescription
					local foundDescription = player:FindFirstChild("_KHumanoidDescription") :: HumanoidDescription?
					if foundDescription then
						if foundDescription:GetAttribute("_KNoob") then
							return foundDescription
						end
						foundDescription:Destroy()
					end
					local newDescription = humanoid:GetAppliedDescription()
					newDescription.Name = "_KHumanoidDescription"
					newDescription:SetAttribute("_KNoob", true)
					newDescription.Parent = player
					return newDescription
				end,
			}
		end,
		run = function(context, players)
			local crmCommand = context._K.Registry.commands.crm
			if not crmCommand then
				return
			end
			for _, player in players do
				local character = player.Character
				local humanoid = character and player.Character:FindFirstChildOfClass("Humanoid")

				if humanoid then
					local description = context.env.getDescription(player, humanoid):Clone()
					for k, v in context.env.properties do
						description[k] = v
					end
					task.defer(function()
						humanoid:ApplyDescription(description, Enum.AssetTypeVerification.Always)
						description:Destroy()
					end)
					for _, child in player.Character:GetChildren() do
						if child:IsA("Accessory") then
							for _, descendant in child:GetDescendants() do
								if descendant:IsA("BasePart") then
									crmCommand.env.updatePart(
										descendant,
										context.env.accessoryColors[child.AccessoryType] or context.env.fallback,
										0,
										Enum.Material.Plastic
									)
								elseif descendant:IsA("SurfaceAppearance") then
									if not descendant:FindFirstChild("_KParent") then
										local _KParent = Instance.new("ObjectValue")
										_KParent.Name = "_KParent"
										_KParent.Value = descendant.Parent
										_KParent.Parent = descendant
										descendant.Parent = humanoid
									end
								end
							end
						end
					end
				end
			end
		end,
	},
	{
		name = "slippery",
		aliases = { "iceskate", "icewalk", "slide" },
		description = "Makes one or more player(s) slide when they walk",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to make slippery.",
				shouldRequest = true,
			},
		},
		envClient = function(_K)
			local thread
			_K.Remote.Slippery:Connect(function(bodyVelocity: BodyVelocity?)
				if typeof(thread) == "thread" and coroutine.status(thread) == "suspended" then
					task.cancel(thread)
					thread = nil
				end
				if bodyVelocity then
					thread = task.spawn(function()
						while bodyVelocity and bodyVelocity.Parent do
							local velocity = (bodyVelocity.Parent :: Part).AssemblyLinearVelocity
							bodyVelocity.Velocity = Vector3.new(velocity.X, 0, velocity.Z)
							task.wait(0.1)
						end
					end)
				end
			end)
		end,
		env = function(_K)
			return {
				remote = _K.Remote.Slippery,
			}
		end,
		run = function(context, players)
			for _, player in players do
				local root = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
				if not root then
					continue
				end

				local existing = root:FindFirstChild("_K_Slippery")
				if existing then
					existing:Destroy()
				end

				if context.undo then
					continue
				end

				context.env.remote:Fire(
					player,
					context._K.Flux.new "BodyVelocity" {
						Name = "_K_Slippery",
						MaxForce = Vector3.new(5000, 0, 5000),
						Parent = root,
					}
				)
			end
		end,
	},
}


-- dangerous commands restricted to superadmins

local Util = require(script.Parent.Parent:WaitForChild("Util"))

return {
	{
		name = "badge",
		aliases = { "awardbadge", "givebadge" },
		description = "Awards a badge to one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to award the badge.",
			},
			{
				type = "integer",
				name = "Badge ID",
				description = "The badge ID.",
			},
		},

		run = function(context, players, badge)
			local service = context._K.Service.Badge
			local tasks = Util.Tasks.new()

			for _, player in players do
				tasks:add(function()
					local ok, result = Util.Retry(service.UserHasBadgeAsync, 5, 2, service, player.UserId, badge)
					if not ok then
						error(result)
					end
					if result then
						context._K.alert(context.fromPlayer, `{player.Name} already has the badge!`)
						return
					else
						local ok2, result2 = Util.Retry(service.AwardBadge, 5, 2, service, player.UserId, badge)
						if not ok2 then
							error(result2)
						end
						return result2
					end
				end)
			end

			local resultsList = tasks:wait()
			for _, results in resultsList do
				local ok, result = results[1], results[2]
				if not ok then
					return `Failed to award badges: {result}`
				end
			end

			context._K.alert(context.fromPlayer, `Badges awarded!`)
			return
		end,
	},
	{
		name = "btools",
		aliases = { "build", "f3x" },
		credit = { "GigsD4X", "Kohl @Scripth" },
		description = "Gives Building Tools by F3X to one or more player(s).",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to give Building Tools by F3X.",
			},
		},
		env = function(_K)
			local env = {}

			task.defer(function()
				env.tool = _K.Tools:WaitForChild("Building Tools") :: Tool
				env.tool.CanBeDropped = false
				local handle = Instance.new("Part")
				handle.Name = "Handle"
				handle.Size = Vector3.new(0.8, 0.8, 0.8)
				handle.CastShadow = false
				handle.CanTouch = false
				handle.CanQuery = false
				handle.TopSurface = 0
				handle.BottomSurface = 0
				for _, face in Enum.NormalId:GetEnumItems() do
					local decal = Instance.new("Decal")
					decal.Face = face
					decal.Texture = "rbxassetid://129748355"
					decal.Parent = handle
				end
				handle.Parent = env.tool
			end)

			return env
		end,

		run = function(context, players)
			for _, player in players do
				local backpack = player:FindFirstChildOfClass("Backpack")
				if not backpack or backpack:FindFirstChild("Building Tools") then
					continue
				end
				context.env.tool:Clone().Parent = backpack
			end
		end,
	},
	{
		name = "chat",
		aliases = { "forcechat" },
		description = "Forces one or more player(s) to chat.",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) who will be forced to chat.",
				shouldRequest = true,
			},
			{
				type = "string",
				name = "Message",
				description = "The chat message to send.",
			},
		},
		envClient = function(_K)
			local function forceChat(message: string)
				_K.Service.TextChat:WaitForChild("TextChannels").RBXGeneral:SendAsync(message)
			end
			_K.Remote.ForceChat:Connect(forceChat)
			_K.forceChat = forceChat
		end,
		env = function(_K)
			return { remote = _K.Remote.ForceChat }
		end,
		run = function(context, players: { Player }, message: string)
			for _, player in players do
				context.env.remote:Fire(player, message)
			end
		end,
	},
	{
		name = "clearterrain",
		aliases = { "cterrain", "clrterrain", "removeterrain" },
		description = "Removes all terrain.",
		args = {},
		run = function(context)
			workspace.Terrain:Clear()
		end,
	},
	{
		name = "explorer",
		description = "Shows the explorer.",
		args = {},
		runClient = function(context)
			context._K.client.Explorer.Show()
		end,
	},
	{
		name = "incognito",
		description = "Hides one or more player(s) from lower rank players. (Persists until rejoin)",
		args = {
			{
				type = "players",
				name = "Player(s)",
				description = "The player(s) to hide.",
				shouldRequest = true,
			},
			{
				type = "boolean",
				name = "Hide Character",
				description = "Hides the character, defaults to true.",
				optional = true,
			},
		},

		envClient = function(_K)
			local env = {
				hidden = _K.UI.state({}),
			}

			local function removeCharacter(name: string)
				local character = workspace:WaitForChild(name)
				if not (character and character:FindFirstChildOfClass("Humanoid")) then
					character = nil
					for _, child in workspace:GetChildren() do
						if child.Name == name and child:IsA("Model") and child:FindFirstChildOfClass("Humanoid") then
							character = child
							break
						end
					end
				end
				if character then
					character:Destroy()
				end
			end

			_K.Remote.Incognito:Connect(
				function(userIdOrName: number | string, hiddenRank: number, hideCharacter: boolean?)
					if type(userIdOrName) == "number" then
						if hideCharacter == nil then -- remove from hidden list
							env.hidden._value[userIdOrName] = nil
							env.hidden(env.hidden._value)
						else
							local player = _K.Service.Players:GetPlayerByUserId(userIdOrName)
							if player then
								env.hidden._value[userIdOrName] = player.Name
								env.hidden(env.hidden._value)
								if hiddenRank > _K.client.rank._value then
									if hideCharacter then
										pcall(game.Destroy, player.Character)
									end
									player:Destroy()
								end
							end
						end
					elseif type(userIdOrName) == "string" and hiddenRank > _K.client.rank._value then
						removeCharacter(userIdOrName)
					end
				end
			)

			_K.Remote.Incognito:Fire()

			return env
		end,

		env = function(_K)
			local env = {
				hidden = {},
				remote = _K.Remote.Incognito :: RemoteEvent,
			}

			function env.apply(hiddenPlayer: Player, hideCharacter: boolean?)
				local hiddenRank = _K.Auth.getRank(hiddenPlayer.UserId)
				if env.hidden[hiddenPlayer] == false and hideCharacter then
					env.remote:FireAll(hiddenPlayer.Name, hiddenRank, hideCharacter)
				else
					env.remote:FireAll(hiddenPlayer.UserId, hiddenRank, hideCharacter)
				end
				env.hidden[hiddenPlayer] = hideCharacter
			end

			local function characterAdded(character)
				local player = _K.Service.Players:GetPlayerFromCharacter(character)
				if env.hidden[player] ~= nil then
					local hiddenRank = _K.Auth.getRank(player.UserId)
					env.remote:FireAll(character.Name, hiddenRank)
				end
			end

			local cleanup = {}

			_K.Util.SafePlayerAdded(function(player: Player)
				cleanup[player] = player.CharacterAdded:Connect(characterAdded)
				if player.Character then
					characterAdded(player.Character)
				end
			end)

			_K.Service.Players.PlayerRemoving:Connect(function(player)
				_K.Flux.cleanup(cleanup[player])
				cleanup[player] = nil
				if env.hidden[player] ~= nil then
					env.hidden[player] = nil
					env.remote:FireAll(player.UserId)
				end
			end)

			env.remote:Connect(function(player)
				for hiddenPlayer, hideCharacter in env.hidden do
					local hiddenRank = _K.Auth.getRank(hiddenPlayer.UserId)
					env.remote:Fire(player, hiddenPlayer.UserId, hiddenRank, hideCharacter)
				end
			end)

			return env
		end,

		run = function(context, players: { Player }, hideCharacter: boolean?)
			if hideCharacter == nil then
				hideCharacter = true
			end
			for _, player in players do
				context.env.apply(player, hideCharacter)
			end
		end,
	},
	{
		name = "incognitolist",
		description = "Views all incognito players in the server.",

		envClient = function(_K)
			local UI = _K.UI

			local hidden = _K.Registry.commands.incognito.env.hidden

			local scroller = UI.new "ScrollerFast" {
				List = hidden,
				Enabled = true,
				DictList = true,
				FilterInput = true,
				ReverseOrder = true,
				Visible = true,
				CreateItem = function(self, lineData)
					return UI.new "Frame" {
						BackgroundTransparency = 1,
						Size = self.ItemSize,

						UI.new "UIPadding" {
							PaddingTop = UI.Theme.PaddingHalf,
							PaddingBottom = UI.Theme.PaddingHalf,
						},

						UI.new "UIListLayout" {
							VerticalAlignment = Enum.VerticalAlignment.Center,
							FillDirection = Enum.FillDirection.Horizontal,
							SortOrder = Enum.SortOrder.LayoutOrder,
							Padding = UI.Theme.Padding,
						},

						UI.new "ImageLabel" {
							BackgroundTransparency = UI.Theme.TransparencyHeavy,
							BackgroundColor3 = UI.Theme.PrimaryText,
							Size = UDim2.new(1, 0, 1, 0),
							SizeConstraint = Enum.SizeConstraint.RelativeYY,

							UI.new "UICorner" {
								CornerRadius = UDim.new(1, 0),
							},
							UI.new "Stroke" {},
						},

						UI.new "TextLabel" {
							AutoLocalize = false,
							AutomaticSize = Enum.AutomaticSize.X,
							BackgroundTransparency = 1,
							Size = UDim2.new(0, 0, 1, 0),
							RichText = true,
							FontFace = UI.Theme.FontMono,
							TextSize = UI.Theme.FontSize,
							TextColor3 = UI.Theme.PrimaryText,
							TextStrokeColor3 = UI.Theme.Primary,
							TextStrokeTransparency = UI.Theme.TextStrokeTransparency,
							TextTruncate = Enum.TextTruncate.SplitWord,
							TextXAlignment = Enum.TextXAlignment.Left,

							UI.new "UIFlexItem" { FlexMode = Enum.UIFlexMode.Fill },
						},
					}
				end,
				RenderItem = function(self, lineItem, lineData)
					lineItem.ImageLabel.Image = `rbxthumb://type=AvatarHeadShot&id={lineData}&w=48&h=48`
					lineItem.TextLabel.Text =
						`<b>{hidden._value[lineData]}</b> <font transparency="0.5">[{lineData}]</font>`
				end,
			}

			UI.edit(scroller._scroller, {
				UI.new "UIFlexItem" {
					FlexMode = Enum.UIFlexMode.Fill,
				},
			})

			UI.edit(scroller._instance, {
				UI.new "UIPadding" {
					PaddingTop = UI.Theme.PaddingStroke,
					PaddingBottom = UI.Theme.PaddingStroke,
					PaddingLeft = UI.Theme.PaddingStroke,
					PaddingRight = UI.Theme.PaddingStroke,
				},
			})

			return {
				scroller = scroller,
				window = UI.new "Window" {
					Parent = UI.LayerTopInset,
					Title = "Incognito Players",
					Exitable = true,
					Position = UDim2.new(0.5, -128, 0.5, -128),
					Size = UDim2.new(0, 256, 0, 256),

					scroller,
				},
			}
		end,
		runClient = function(context, player)
			context.env.window._instance.Visible = true
		end,
	},
	{
		name = "reserve",
		aliases = { "privateserver" },
		description = "Reserves a private server.",
		args = {
			{
				type = "rawString",
				name = "AccessCode",
				description = "The access code for joining the reserved server.",
			},
			{
				type = "integer",
				name = "PlaceId",
				description = "The place identifier, omit for the current place.",
				optional = true,
			},
		},
		env = function(_K)
			local remote = _K.Remote.ReservedServers
			task.spawn(
				_K.Service.Messaging.SubscribeAsync,
				_K.Service.Messaging,
				"_K_ReservedServers",
				function(message)
					local data = message.Data
					if type(data) == "table" then
						_K.Data.reservedServers[data[1]] = data
						for _, player in _K.Service.Players:GetPlayers() do
							if
								_K.Auth.hasCommand(player.UserId, "place")
								or _K.Auth.hasCommand(player.UserId, "unreserve")
							then
								remote:Fire(player, { [data[1]] = data })
							end
						end
					elseif type(data) == "string" then
						_K.Data.reservedServers[data] = nil
						remote:FireAll(data)
					end
				end
			)
			return { remote = remote }
		end,
		envClient = function(_K)
			_K.Remote.ReservedServers:Connect(function(data)
				if type(data) == "table" then
					_K.Util.Table.merge(_K.Data.reservedServers, data)
				elseif type(data) == "string" then
					_K.Data.reservedServers[data] = nil
				end
			end)
		end,
		run = function(context, code: string, placeId: number?)
			if context._K.Data.SEPARATE_DATASTORE then
				return `Reserve command is disabled in private servers.`
			end

			if context._K.Data.reservedServers[code] then
				return `Server "<b>{code}</b>" is already reserved.`
			end

			placeId = placeId or game.PlaceId
			local data = { code, context._K.Service.Teleport:ReserveServer(placeId), placeId }
			context._K.Data.Store.updateAsync("Servers", function(store)
				if store == nil then
					store = {}
				end

				-- convert to new format
				for k, v in store do
					if #v == 2 then
						store[k] = { k, v[1], v[2] }
					end
				end

				store[code] = data
				return store
			end)

			context.env.remote:FireAll({ [code] = data })
			context._K.Service.Messaging:PublishAsync("_K_ReservedServers", data)
			context._K.Remote.Notify:Fire(context.fromPlayer, {
				Text = `Server "<b>{code}</b>" has been reserved, use <b>{context._K.getCommandPrefix(context.from)}place me @{code}</b> to join it!`,
			})

			return
		end,
	},
	{
		name = "unreserve",
		aliases = { "delreserve", "removereserve", "removeprivateserver" },
		description = "Removes a reserved server.",
		args = {
			{
				type = "reservedServer",
				name = "AccessCode",
				description = "The access code of the reserved server.",
			},
		},
		run = function(context, data)
			if context._K.Data.SEPARATE_DATASTORE then
				return `Unreserve command is disabled in private servers.`
			end

			local code = data[1]
			local removed
			context._K.Data.Store.updateAsync("Servers", function(store)
				if store == nil then
					store = {}
				end

				if store[code] then
					removed = true
				end
				store[code] = nil

				return store
			end)

			context._K.Remote.ReservedServers:FireAll(code)
			context._K.Service.Messaging:PublishAsync("_K_ReservedServers", code)
			context._K.Remote.Notify:Fire(context.fromPlayer, {
				Text = `Server "<b>{code}</b>" {if removed then "has been removed" else "was NOT found"}!`,
			})

			return
		end,
	},
	{
		name = "shutdown",
		aliases = { "stopserver" },
		description = "Shuts down the server.",
		args = {
			{
				type = "timeSimple",
				name = "Delay",
				description = "The delay before shutting down.",
				optional = true,
			},
			{
				type = "string",
				name = "Reason",
				description = "The reason for the shutdown.",
				optional = true,
			},
		},
		run = function(context, delay: number?, reason: string?)
			if delay ~= nil then
				context._K.Remote.Announce:FireAll({
					Text = `Server will shut down in {delay} seconds`,
					From = context.from,
					Duration = delay,
				})
				task.wait(delay)
			end
			local from = tostring(context.fromPlayer or context.from)
			local function kick(player)
				player:Kick(`{from} has shutdown the server.{if reason then `\nReason: {reason}` else ""}`)
			end
			game:GetService("Players").PlayerAdded:Connect(kick)
			for _, player in game:GetService("Players"):GetPlayers() do
				kick(player)
			end
		end,
	},
	{
		name = "global",
		aliases = { "gcmd" },
		description = "Runs a command string globally in all servers.",
		args = {
			{
				type = "rawString",
				name = "Command string",
				description = "The command string to run.",
			},
		},
		env = function(_K)
			task.spawn(function()
				_K.Service.Messaging:SubscribeAsync("KA_GlobalCommand", function(message)
					if type(message.Data) == "string" then
						message.Data = Util.Service.Http:JSONDecode(message.Data)
					end
					if type(message.Data) ~= "table" then
						return
					end
					local from, commandString = unpack(message.Data)
					if from and commandString then
						_K.Process.runCommands(_K, from, commandString, true, true)
					end
				end)
			end)

			return
		end,
		run = function(context, commandString: string)
			if context.global then
				return
			end

			if context._K.Data.SEPARATE_DATASTORE then
				return `Global commands are disabled in private servers.`
			end

			local prefix = context._K.getCommandPrefix(context.from)
			if string.find(commandString, string.format('^%s[^%s"`,%%s]', prefix, prefix)) ~= 1 then
				commandString = prefix .. commandString
			end

			local ok, result = context._K.Process.prepareCommands(context._K, context.from, commandString)
			if not ok then
				return result
			end

			local commandStrings = {}
			local msgCommands = { "hint", "privatehint", "message", "privatemessage", "fullmessage", "notify" }

			for index, command in result do
				if not command.definition.args then
					local last = command.array[#command.array]
					table.insert(commandStrings, string.sub(commandString, command.array[1][1], last[1] + #last[2]))
				end

				local argType = if table.find(msgCommands, command.definition.name) then "rawString" else "string"
				local argStrings = {}
				for i, arg in command.definition.args do
					if arg.type == argType then
						local filtered = context._K.Util.String.filterForBroadcast(command.args[i].rawArg, context.from)
						table.insert(argStrings, filtered)
					else
						table.insert(argStrings, command.args[i].rawArg)
					end
				end

				table.insert(commandStrings, `{prefix}{command.definition.name} {table.concat(argStrings, " ")}`)
			end

			commandString = table.concat(commandStrings, " ")
			context._K.Service.Messaging:PublishAsync("KA_GlobalCommand", { context.from, commandString })
			return
		end,
	},
}