local M={DefaultGroupID=0}local g={}local b=game:GetService("\071\114\111\117\112\083\101\114\118\105\099\101")g.dataCache=setmetatable({},{__index=function(M,g)M[g]=setmetatable({},{__index=function(M,g)M[g]={}return M[g]end})return M[g]end})g.FetchPlayerInfo=function(g,h,t)if not t and not M.DefaultGroupID then return error("\065\116\116\101\109\112\116 \116\111 \102\101\116\099\104 \112\108\097\121\101\114 \114\097\110\107 \119\105\116\104\111\117\116 \115\112\101\099\105\102\121\105\110\103 \103\114\111\117\112\046 \073\115 \097 \100\101\102\097\117\108\116 \103\114\111\117\112 \115\101\116\063")elseif not t and M.DefaultGroupID then t=M.DefaultGroupID end local V,k=pcall(function()return b:GetGroupsAsync(h.UserId)end)if not V then warn("\091\082\097\110\107\067\097\099\104\101\093 \070\097\105\108\101\100 \116\111 \102\101\116\099\104 \103\114\111\117\112 \040\073\068\058 "..(t..("\041 \100\097\116\097 \102\111\114 "..(h.Name..(" \040"..(h.UserId.."\041"))))))return{Rank=0;Role="\071\117\101\115\116"}end local B=0 local Q="\071\117\101\115\116"for M,g in pairs(k)do if g.Id==t then B=g.Rank Q=g.Role break end end g.dataCache[h.UserId][t]={Rank=B;Role=Q}return g.dataCache[h.UserId][t]end g.ClearPlayerInfo=function(M,g)M.dataCache[g.UserId]=nil end g.GetPlayerRank=function(g,b,h)if not h and not M.DefaultGroupID then return error("\065\116\116\101\109\112\116 \116\111 \102\101\116\099\104 \112\108\097\121\101\114 \114\097\110\107 \119\105\116\104\111\117\116 \115\112\101\099\105\102\121\105\110\103 \103\114\111\117\112\046 \073\115 \097 \100\101\102\097\117\108\116 \103\114\111\117\112 \115\101\116\063")elseif not h and M.DefaultGroupID then h=M.DefaultGroupID end if g.dataCache[b.UserId][h].Rank then return g.dataCache[b.UserId][h].Rank end local t=g:FetchPlayerInfo(b,h)return t.Rank end g.GetPlayerRole=function(g,b,h)if not h and not M.DefaultGroupID then return error("\065\116\116\101\109\112\116 \116\111 \102\101\116\099\104 \112\108\097\121\101\114 \114\097\110\107 \119\105\116\104\111\117\116 \115\112\101\099\105\102\121\105\110\103 \103\114\111\117\112\046 \073\115 \097 \100\101\102\097\117\108\116 \103\114\111\117\112 \115\101\116\063")elseif not h and M.DefaultGroupID then h=M.DefaultGroupID end if g.dataCache[b.UserId][h].Role then return g.dataCache[b.UserId][h].Role end local t=g:FetchPlayerInfo(b,h)return t.Role end return g
--[[
    Whitehill Rank Cache Module
    Author: TheCakeChicken

    This module can be required from both the client and the server.

    This module is designed to provide the developer with greater control over how group ranks/roles are handled in their game.
    Games which rely on these usually use Player:GetRankInGroup, which caches even after a player rejoins.

    You may wish to consider implementing a server script to fetch/clear this data when a player joins/leaves
    to ensure that when a player rejoins the game, the latest ranking information is fetched and used.

    TO SETUP:
        - Place this ModuleScript into ReplicatedStorage
        - Set relevant settings in the config table

    USAGE:
        -- Load the library
        local rankCache = require(game.ReplicatedStorage.RankCache)

        -- Fetches Player1's rank for group 1234
        local player1Rank = rankCache:GetPlayerRank(game.Players.Player1, 1234)

        -- Fetches Player1's role for group 1234
        local player1Role = rankCache:GetPlayerRole(game.Players.Player1, 1234)

        -- Fetches Player2's rank for the configured default group
        local player2Rank = rankCache:GetPlayerRank(game.Players.Player2)

        -- Fetches Player2's role for the configured default group
        local player2Role = rankCache:GetPlayerRole(game.Players.Player2)


    More advanced usage can be found within the GitHub repository.

    Need help?
    Check out the example scripts available in the GitHub repository
]]

local config = {
	--// Specifies the group ID to use when no groupId is provided
	DefaultGroupID = 0;
}

local module = {}

local GroupService = game:GetService('GroupService')

module.dataCache = setmetatable({}, {
	__index = function(t,i)
		t[i] = setmetatable({}, {__index = function(t_,i_) t_[i_] = {} return t_[i_] end})
		return t[i]
	end
})

module.FetchPlayerInfo = function(self, player, groupId)
	if (not groupId and not config.DefaultGroupID) then
		return error("Attempt to fetch player rank without specifying group. Is a default group set?")
	elseif (not groupId and config.DefaultGroupID) then
		groupId = config.DefaultGroupID
	end

	local isSuccess, usrGroups = pcall(function() return GroupService:GetGroupsAsync(player.UserId) end)

    --// If the request failed, return a default value but do not store to the cache, so subsequent requests will attempt to fetch new data
    if (not isSuccess) then
        warn("[RankCache] Failed to fetch group (ID: " .. groupId .. ") data for " .. player.Name .. " (" .. player.UserId .. ")");

        return {
            Rank = 0;
            Role = "Guest";
        }
    end

	local playerRank = 0
	local playerRole = "Guest"

	for _, group in pairs(usrGroups) do
		if group.Id == groupId then
			playerRank = group.Rank;
			playerRole = group.Role;

			break;
		end
	end

	self.dataCache[player.UserId][groupId] = {
		Rank = playerRank;
		Role = playerRole;
	}

	return self.dataCache[player.UserId][groupId]
end

module.ClearPlayerInfo = function(self, player)
	self.dataCache[player.UserId] = nil
end

module.GetPlayerRank = function(self, player, groupId)
	if (not groupId and not config.DefaultGroupID) then
		return error("Attempt to fetch player rank without specifying group. Is a default group set?")
	elseif (not groupId and config.DefaultGroupID) then
		groupId = config.DefaultGroupID
	end

	if self.dataCache[player.UserId][groupId].Rank then
		return self.dataCache[player.UserId][groupId].Rank
	end

	local data = self:FetchPlayerInfo(player, groupId)
	return data.Rank
end

module.GetPlayerRole = function(self, player, groupId)
	if (not groupId and not config.DefaultGroupID) then
		return error("Attempt to fetch player rank without specifying group. Is a default group set?")
	elseif (not groupId and config.DefaultGroupID) then
		groupId = config.DefaultGroupID
	end

	if self.dataCache[player.UserId][groupId].Role then
		return self.dataCache[player.UserId][groupId].Role
	end

	local data = self:FetchPlayerInfo(player, groupId)
	return data.Role
end

return module
