New code sample for Group Ally/Enemy Checker on GroupService article: improvements, spelling mistakes and better formatting

I’d like to propose a change to the Group Ally/Enemy Checker code sample which shows how to use GroupService in actual work. The new code sample tackles the following areas:

  • General code improvements, ensuring current standards are used.

  • Fixes on spelling mistakes that could cause erroring or are simply not correct to use.

  • Improved formatting.

local GroupService = game:GetService("GroupService")
local Players = game:GetService("Players")

-- define group id here
local GROUP_ID = 271454

-- utility function for dealing with pages
local function pagesToArray(pages)
    local array = {}
    while true do
        for _, v in ipairs(pages:GetCurrentPage()) do
            table.insert(array, v)
        end
        if pages.IsFinished then
            break
        end
        pages:AdvanceToNextPageAsync()
    end
    return array
end

-- get lists of allies and enemies
local alliesPages = GroupService:GetAlliesAsync(GROUP_ID)
local enemiesPages = GroupService:GetEnemiesAsync(GROUP_ID)

-- convert to array
local allies = pagesToArray(alliesPages)
local enemies = pagesToArray(enemiesPages)

local function playerAdded(player)
    -- check to see if the player is in the group
    if player:IsInGroup(GROUP_ID) then
        print(player.Name .. " is a member!")
    else
        local isAlly, isEnemy = false, false

        -- check to see if the player is in any ally groups
        for _, groupInfo in ipairs(allies) do
            local groupId = groupInfo.Id
            if player:IsInGroup(groupId) then
                isAlly = true
                break
            end
        end

        -- check to see if the player is in any enemy groups
        for _, groupInfo in ipairs(enemies) do
            local groupId = groupInfo.Id
            if player:IsInGroup(groupId) then
                isEnemy = true
                break
            end
        end

        if isAlly and not isEnemy then
            print(player.Name .. " is an ally!")
        elseif isEnemy and not isAlly then
            print(player.Name .. " is an enemy!")
        elseif isEnemy and isAlly then
            print(player.Name .. " is both an ally and an enemy!")
        else
            print(player.Name .. " is neither an ally or an enemy!")
        end
    end
end

-- listen for new players being added
Players.PlayerAdded:Connect(playerAdded)

-- handle players already in game
for _, player in ipairs(Players:GetPlayers()) do
    playerAdded(player)
end

The following changes in this code sample were made in comparison to the current sample:

  • Sample is properly formatted. Previous sample was all tabbed by one except for the very first line.

  • All cases of pairs were changed to ipairs. This sample does not work with dictionaries in any scope, so I opted to change the iterator used. The StandardPages returned by GetAllies/EnemiesAsync always return contiguous arrays per page. GetPlayers always returns an array as well.

  • First variable in the for loop of pagesToArray was changed from k to an underscore. This was not consistent with all other for loops which used an underscore for the first variable. I also used value for the second variable because that’s more readable than a single letter and it represents the idea of key-value pairs for pages.

  • Removed the useless conditional check in the for loops intended to set isAlly and isEnemy. When iterating through the allies and enemies arrays, all the elements are guaranteed to exist, it won’t iterate over a nil value. If this was to account for edge cases, then the if check should have been done before trying to index a member item, as that would throw an error. Fixed example, if the edge case conditional is required, available below.

for _, groupInfo in pairs(GROUP_TYPE_TABLE)) do
    if groupInfo then
        local groupId = groupInfo.Id
        if groupId and player:IsInGroup(groupId) then
            isGROUPTYPE = true
            break
        end
    end
end
2 Likes

Thanks for reporting this - I’ve added it to our todo list!

4 Likes

Housekeeping: this was resolved a long time ago on the Developer Hub and has also carried over to the Creator Documentation (the code sample I proposed got used :flushed:).

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.