local a=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local C=game:GetService("\080\108\097\121\101\114\115")local P=require(script.Parent:WaitForChild("\117\117\105\100",1))local B={}function B.CreateFolder(a,C)local P=Instance.new("\070\111\108\100\101\114")P.Name=a P.Parent=C return P end function B.FindSiblingNamed(a,C)if a.Parent~=nil then if a.Parent:FindFirstChild(C,false)~=nil then return a.Parent:FindFirstChild(C,false)end end return nil end function B.DeepCopyTable(a)local C=type(a)local P if C=="\116\097\098\108\101"then P={}for a,C in next,a,nil do P[B.DeepCopyTable(a)]=B.DeepCopyTable(C)end setmetatable(P,B.DeepCopyTable(getmetatable(a)))else P=a end return P end function B.GetPlayerFromCharacterOrDescendant(a)local P=a local B=nil while not B do if P~=nil and P:FindFirstChild("\072\117\109\097\110\111\105\100")~=nil then print("\070\111\117\110\100 \097 \104\117\109\097\110\111\105\100\033")B=C:GetPlayerFromCharacter(P)return B end print(P.Name)if P~=nil and P.Parent~=nil then P=P.Parent if P.Name=="\087\111\114\107\115\112\097\099\101"then return nil end end if P==nil then return B end end return B end function B.GetPlayerDrivingVehicle(a)if a~=nil and(a:FindFirstChild("\086\101\104\105\099\108\101\083\101\097\116")~=nil and(a:FindFirstChild("\086\101\104\105\099\108\101\083\101\097\116")).Occupant~=nil)then local P=(a:FindFirstChild("\086\101\104\105\099\108\101\083\101\097\116")).Occupant.Parent local B=C:GetPlayerFromCharacter(P)return B end return nil end function B.PersonageTorsoOrEquivalent(a)local C=a:FindFirstChild("\084\111\114\115\111")if C==nil then C=a:FindFirstChild("\085\112\112\101\114\084\111\114\115\111")end return C end function B.GetPersonageOrPlayerHumanoidOrNil(a)if a:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")~=nil then return a:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")end local C=a.Character if not C then return nil end return C:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")end function B.GetHumanoid(a)local C=a while C do local a=C:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if a then return a end C=C.Parent end return nil end function B.AttachedHumanoidOrNil(a)if a==nil then return nil end if B.FindSiblingNamed(a,"\072\117\109\097\110\111\105\100")~=nil then return B.FindSiblingNamed(a,"\072\117\109\097\110\111\105\100")elseif a:FindFirstAncestor("\072\117\109\097\110\111\105\100")~=nil then return a:FindFirstAncestor("\072\117\109\097\110\111\105\100")elseif a:FindFirstChild("\072\117\109\097\110\111\105\100",false)~=nil then return a:FindFirstChild("\072\117\109\097\110\111\105\100",false)end return B.GetHumanoid(a)end function B.AttachedCharacterOrNil(a)local C=B.AttachedHumanoidOrNil(a)if C~=nil then local a=C.Parent if a~=nil then return a end end return nil end function B.GetAlivePersonageOrPlayerHumanoid(a)local C=B.GetPersonageOrPlayerHumanoidOrNil(a)if not C or C.Health<=0 then return nil end return C end function B.GetAlivePersonageOrPlayerRootPart(a)local C=B.GetPersonageOrPlayerHumanoidOrNil(a)if not C or C.Health<=0 then return nil end return C.RootPart end function B.GetPersonageOrPlayerRootPart(a)local C=B.GetPersonageOrPlayerHumanoidOrNil(a)if not C then return nil end return C.RootPart end function B.UnequipTools(a)local C=B.GetPersonageOrPlayerHumanoidOrNil(a)if C then C:UnequipTools()end end function B.GetUserIdString(a)return tostring(a.UserId)end function B.GetUserIdFromCharacter(a)local P=C:GetPlayerFromCharacter(a)if P then return B.GetUserIdString(P)end end function B.GetPlayerFromUserId(a)for C,P in pairs(C:GetPlayers())do if P.UserId==tonumber(a)then return P end end end function B.GetCharacterFromUserId(a)local C=B.GetPlayerFromUserId(a)if C then return C.Character end end function B.FolderContentsOrNil(a,C)if a==nil or C==nil then return nil end local P=C:FindFirstChild(a)if P~=nil and P:IsA("\070\111\108\100\101\114")then return P:GetChildren()end return nil end function B.ForceUnseatHumanoid(a)if a.SeatPart then local C=a.SeatPart:FindFirstChild("\083\101\097\116\087\101\108\100")if C then C:Destroy()end a.SeatPart:Sit(nil)end a.Sit=false end function B.ComponentsFolderOrNil(a)return B.FolderContentsOrNil("\067\111\109\112\111\110\101\110\116\115",a)end function B.StringValueOrNil(a,C)if a==nil or C==nil then return nil end local P=C:FindFirstChild(a)if P~=nil and P:IsA("\083\116\114\105\110\103\086\097\108\117\101")then return P.Value end return nil end function B.BoolValueOrNil(a,C)if a==nil or C==nil then return nil end local P=C:FindFirstChild(a)if P~=nil and P:IsA("\066\111\111\108\086\097\108\117\101")then return P.Value end return nil end function B.ObjectValueOrNil(a,C)if a==nil or C==nil then return nil end local P=C:FindFirstChild(a)if P~=nil and P:IsA("\079\098\106\101\099\116\086\097\108\117\101")then return P.Value end return nil end function B.IntValueOrNil(a,C)if a==nil or C==nil then return nil end local P=C:FindFirstChild(a)if P~=nil and P:IsA("\079\098\106\101\099\116\086\097\108\117\101")then return P.Value end return nil end function B.GetOrAddItem(a,C,P)if a==nil or C==nil or P==nil then return nil end local B=P:FindFirstChild(a)if B==nil then B=Instance.new(C)B.Name=a B.Parent=P end return B end function B.GetOrAddEntityId(a)local C=B.GetOrAddItem("\069\110\116\105\116\121\073\100","\083\116\114\105\110\103\086\097\108\117\101",a)if C.Value==nil or C.Value==""then C.Value=P()end return C.Value end function B.Assign(a,...)for C=1,select("\035",...),1 do local P=select(C,...)for C,P in pairs(P)do a[C]=P end end return a end return B
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlayersService = game:GetService("Players")
--local t = require(script.Parent.Parent.lib.t)

local uuid = require(script.Parent:WaitForChild("uuid", 1))

local module = {}

function module.CreateFolder( folderName, parentObjectInstance )
	local folderInst = Instance.new("Folder")
	folderInst.Name = folderName
	folderInst.Parent = parentObjectInstance
	return folderInst
end

function module.FindSiblingNamed( part, siblingName )
	if part.Parent ~= nil then
		if part.Parent:FindFirstChild( siblingName, false ) ~= nil then
			return part.Parent:FindFirstChild( siblingName, false )
		end
	end

	return nil
end

function module.DeepCopyTable(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[module.DeepCopyTable(orig_key)] = module.DeepCopyTable(orig_value)
        end
        setmetatable(copy, module.DeepCopyTable(getmetatable(orig)))
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end
--- Returns the Player and Character that a descendent is part of, if it is part of one.
-- @param descendant A child of the potential character.
-- @treturn Player player
-- @treturn Character charcater
function module.GetPlayerFromCharacterOrDescendant(descendantCharacter)
	local characterCandidate = descendantCharacter
	local player = nil

	while not player do
		if characterCandidate ~= nil and characterCandidate:FindFirstChild("Humanoid") ~= nil then
			print("Found a humanoid!")
			player = PlayersService:GetPlayerFromCharacter(characterCandidate)
			return player
		end
		print(characterCandidate.Name)
		if characterCandidate ~= nil and characterCandidate.Parent ~= nil then
			characterCandidate = characterCandidate.Parent
			if characterCandidate.Name == "Workspace" then
				return nil
			end
		end
		if characterCandidate == nil then
			return player
		end
	end

	return player
end

function module.GetPlayerDrivingVehicle(vehicleModel)
    if vehicleModel ~= nil and
         vehicleModel:FindFirstChild("VehicleSeat") ~= nil and 
         vehicleModel:FindFirstChild("VehicleSeat").Occupant ~= nil then
            local occupantCharacter = vehicleModel:FindFirstChild("VehicleSeat").Occupant.Parent
            local occupantPlayer = PlayersService:GetPlayerFromCharacter(occupantCharacter)
            return occupantPlayer
         end

    return nil
end

function module.PersonageTorsoOrEquivalent(personage)
	local personageTorso = personage:FindFirstChild("Torso")
	if personageTorso == nil then
		personageTorso = personage:FindFirstChild("UpperTorso")
	end
	return personageTorso
end
function module.GetPersonageOrPlayerHumanoidOrNil(personageOrPlayer)
	if personageOrPlayer:FindFirstChildOfClass("Humanoid") ~= nil then
		return personageOrPlayer:FindFirstChildOfClass("Humanoid")
	end
	local character = personageOrPlayer["Character"]
	if not character then
		return nil
	end

	return character:FindFirstChildOfClass("Humanoid")
end

--- Retrieves a humanoid from a descendant (Players only).
-- @param descendant Child of a humanoid model, like a limb
-- @return Humanoid
function module.GetHumanoid(descendantPart)
	local characterCandidate = descendantPart
	while characterCandidate do
		local humanoid = characterCandidate:FindFirstChildOfClass("Humanoid")
		if humanoid then
			return humanoid
		end
		characterCandidate = characterCandidate.Parent
	end

	return nil
end

function module.AttachedHumanoidOrNil(part)
	if part == nil then return nil end
	
	if module.FindSiblingNamed(part, "Humanoid") ~= nil then
		return module.FindSiblingNamed(part, "Humanoid")
	elseif part:FindFirstAncestor("Humanoid") ~= nil then
		return part:FindFirstAncestor("Humanoid")
	elseif part:FindFirstChild( "Humanoid", false ) ~= nil then
		return part:FindFirstChild( "Humanoid", false )
	end
	return module.GetHumanoid(part)
end

function module.AttachedCharacterOrNil( part )

	local attachedHumanoid = module.AttachedHumanoidOrNil(part)
	if attachedHumanoid ~= nil then
		local character = attachedHumanoid.Parent
		if character ~= nil then
			return character
		end
	end

	return nil
end


function module.GetAlivePersonageOrPlayerHumanoid(personageOrPlayer)
	local humanoid = module.GetPersonageOrPlayerHumanoidOrNil(personageOrPlayer)
	if not humanoid or humanoid.Health <= 0 then
		return nil
	end

	return humanoid
end

function module.GetAlivePersonageOrPlayerRootPart(personageOrPlayer)
	local humanoid = module.GetPersonageOrPlayerHumanoidOrNil(personageOrPlayer)
	if not humanoid or humanoid.Health <= 0 then
		return nil
	end

	return humanoid.RootPart
end

function module.GetPersonageOrPlayerRootPart(personageOrPlayer)
	local humanoid = module.GetPersonageOrPlayerHumanoidOrNil(personageOrPlayer)
	if not humanoid then
		return nil
	end

	return humanoid.RootPart
end

function module.UnequipTools(personageOrPlayer)
	local humanoid = module.GetPersonageOrPlayerHumanoidOrNil(personageOrPlayer)
	if humanoid then
		humanoid:UnequipTools()
	end
end


function module.GetUserIdString(player)
	--assert(getUserIdCheck(player))
	return tostring(player.UserId)
end
--local getCharacterFromUserIdCheck = t.instanceOf("Model")
function module.GetUserIdFromCharacter(character)
	--assert(getCharacterFromUserIdCheck(character))
	local player = PlayersService:GetPlayerFromCharacter(character)

	if player then
		return  module.GetUserIdString(player)
	end
end
--local getPlayerFromUserCheck = t.string
function module.GetPlayerFromUserId(userId)
	--assert(getPlayerFromUserCheck(userId))

	for _, player in pairs(PlayersService:GetPlayers()) do
		if player.UserId == tonumber(userId) then
			return player
		end
	end
end

--[[
	Gets a character from their player's UserId.
]]
--local getCharacterFromUserIdCheck = t.string
function module.GetCharacterFromUserId(userId)
	--assert(getCharacterFromUserIdCheck(userId))
	local player = module.GetPlayerFromUserId(userId)
	if player then
		return player.Character
	end
end

function module.FolderContentsOrNil( folderName, parent )
	if folderName == nil or parent == nil then return nil end

	local folderCandidate = parent:FindFirstChild(folderName)

	if  folderCandidate ~= nil and folderCandidate:IsA("Folder") then
		return folderCandidate:GetChildren()
	end

	return nil
end

--- Forcefully unseats the humanoid. Useful when teleporting humanoid
function module.ForceUnseatHumanoid(humanoid)
	if humanoid.SeatPart then
		local weld = humanoid.SeatPart:FindFirstChild("SeatWeld")
		if weld then
			weld:Destroy()
		end

		humanoid.SeatPart:Sit(nil)
	end
	humanoid.Sit = false
end

function module.ComponentsFolderOrNil( item )
	return module.FolderContentsOrNil( "Components", item )
end

function module.StringValueOrNil( valueName, parent )
	if valueName == nil or parent == nil then return nil end

	local valueCandidate = parent:FindFirstChild(valueName)
	if valueCandidate ~= nil and valueCandidate:IsA("StringValue") then
		return valueCandidate.Value
	end

	return nil
end

function module.BoolValueOrNil( valueName, parent )
	if valueName == nil or parent == nil then return nil end

	local valueCandidate = parent:FindFirstChild(valueName)
	if valueCandidate ~= nil and valueCandidate:IsA("BoolValue") then
		return valueCandidate.Value
	end

	return nil
end

function module.ObjectValueOrNil( valueName, parent )
	if valueName == nil or parent == nil then return nil end

	local valueCandidate = parent:FindFirstChild(valueName)
	if valueCandidate ~= nil and valueCandidate:IsA("ObjectValue") then
		return valueCandidate.Value
	end

	return nil
end

function module.IntValueOrNil( valueName, parent )
	if valueName == nil or parent == nil then return nil end

	local valueCandidate = parent:FindFirstChild(valueName)
	if valueCandidate ~= nil and valueCandidate:IsA("ObjectValue") then
		return valueCandidate.Value
	end

	return nil
end


function module.GetOrAddItem( itemName, itemType, parent )
	if itemName == nil or itemType == nil or parent == nil then return nil end

	local itemCandidate = parent:FindFirstChild(itemName)
	if itemCandidate == nil then 
		itemCandidate = Instance.new(itemType)
		itemCandidate.Name = itemName
		itemCandidate.Parent = parent
	end
	return itemCandidate
end

function module.GetOrAddEntityId(item)
	local entityIdObj = module.GetOrAddItem( "EntityId", "StringValue", item )

	if entityIdObj.Value == nil or entityIdObj.Value == "" then
		entityIdObj.Value = uuid()
	end
    return entityIdObj.Value
end

function module.Assign( target, ... )
	for i = 1, select("#", ...) do
		local source = select(i, ...)

		for key, value in pairs(source) do
			target[key] = value
		end
	end

	return target
end

return module
