MadStudioRoblox / ProfileService

Universal session-locked savable table API
https://madstudioroblox.github.io/ProfileService/
Apache License 2.0
292 stars 157 forks source link

Profile already loaded #21

Closed checkm4te8 closed 2 years ago

checkm4te8 commented 2 years ago

[ProfileService]: Profile [Store:"PlayerData";Key:"Player_2908787387"] is already loaded in this session.

Hello, I made a DataHandler ModuleScript for ProfileService and I put functions like PlayerAdded and SetValue, sadly sometimes, not always but about 75% of the time, I get this error: [ProfileService]: Profile [Store:"PlayerData";Key:"Player_2908787387"] is already loaded in this session.

I use this simple code in a script:
DataHandler.PlayerAdded(Player) DataHandler.SetValue(Player, "Kills", 5)

And here is my full ModuleScript:


-- ProfileTemplate table is what empty profiles will default to.
-- Updating the template will not include missing template values
--   in existing player profiles!
local ProfileTemplate = {
    Kills = 0,
    IsPermBanned = false,
    IsACPermBanned = false,
    IsTempBanned = false,
    TempBanEnd = nil,
    HasCirno = false,
    HasHos = false,
    HasUSup = false,
    HasDonate = false,
    secondsPlayed = 0

}

----- Loaded Modules -----

local ProfileService = require(game.ServerScriptService.Modules.ProfileService)

----- Private Variables -----

local Players = game:GetService("Players")
local MarketPlaceService = game:GetService("MarketplaceService")

local ProfileStore = ProfileService.GetProfileStore(
    "PlayerData",
    ProfileTemplate
)

local Profiles = {} -- [player] = profile
local timeTrack = {}
local FunctionTable = {}

local CirnoPassID = 25047910
local HosPassID = 25047956
local DonatePassID = 25047989

----- Private Functions -----

function FunctionTable.ReadValue(Player, value)
    local profile = FunctionTable.GetProfile(Player)
    local ValueToReturn = profile.Data[value]
    return ValueToReturn
end

function FunctionTable.SetValue(Player, DataName, Value)
    local profile = FunctionTable.GetProfile(Player)
    profile.Data[DataName] = Value
end

function FunctionTable.GetProfile(Player)
    local profile = Profiles[Player]
    return profile
end

function FunctionTable.PlayerJoinChecks(profile, Player)
    --Ban check
    if profile.Data.IsPermBanned ~= false then
        Player:Kick("You are currently permanently banned from Overdrive, the reason being: "..profile.Data.IsPermBanned)
        print("Kicked "..Player.Name.." as they are permanently banned for "..profile.Data.IsPermBanned)
    end
    if profile.Data.IsACPermBanned ~= false then
        Player:Kick("You are currently permanently banned from Overdrive.")
        print("Kicked "..Player.Name.." as they are permanently banned by AC for "..profile.Data.IsACPermBanned)
    end

    --Tempban check
    if profile.Data.IsTempBanned ~= false then
        if profile.Data.TempBanEnd ~= nil then
            local formattedtime = "%c"
            local result = os.date(formattedtime, profile.Data.TempBanEnd)
            if profile.Data.TempBanEnd > os.time() then
                Player:Kick("You are currently temporarily banned from Overdrive. This ban is expiring: "..result..". And the reason is: "..profile.Data.IsTempBanned)
                print("Kicked "..Player.Name.." as they are temporarily banned for "..profile.Data.IsTempBanned..". This ban is expiring "..result)
            elseif profile.Data.TempBanEnd < os.time() then
                --Unban if the ban duration is over
                profile.Data.IsTempBanned = false
                profile.Data.TempBanEnd = nil
            end
        end
    end

    --Check and grant gamepasses
    --Check if the player has Cirno
    local cirnoValue = profile.Data.HasCirno
    if cirnoValue == false then
        local OwnsCirno = MarketPlaceService:UserOwnsGamePassAsync(Player.UserId, CirnoPassID)
        if OwnsCirno == true then
            profile.Data.HasCirno = true
        end
    end

    --Check if the player has HoS
    local hosValue = profile.Data.HasHos
    if hosValue == false then
        local OwnsHos = MarketPlaceService:UserOwnsGamePassAsync(Player.UserId, HosPassID)
        if OwnsHos == true then
            profile.Data.HasHos = true
        end
    end

    --Check if the player has Donate
    local donateValue = profile.Data.HasDonate
    if donateValue == false then
        local OwnsDonate = MarketPlaceService:UserOwnsGamePassAsync(Player.UserId, DonatePassID)
        if OwnsDonate == true then
            profile.Data.HasDonate = true
        end
    end
    local KillAmount = Player:WaitForChild("KillCount")
    KillAmount.Value = profile.Data.Kills
end

function FunctionTable.PlayerAdded(player)
    local ProfileKey = "Player_"..player.UserId
    local profile = ProfileStore:LoadProfileAsync(ProfileKey, "ForceLoad")
    if profile ~= nil then
        profile:AddUserId(player.UserId) -- GDPR compliance
        profile:Reconcile() -- Fill in missing variables from ProfileTemplate (optional)
        profile:ListenToRelease(function()
            Profiles[player] = nil
            -- The profile could've been loaded on another Roblox server:
            player:Kick("Your data storage profile has been loaded on another server, please rejoin.")
        end)
        if player:IsDescendantOf(Players) == true then
            Profiles[player] = profile
            -- A profile has been successfully loaded:
            timeTrack[player] = tick()
            FunctionTable.PlayerJoinChecks(profile, player)
        else
            -- Player left before the profile loaded:
            profile:Release()
        end
    else
        -- The profile couldn't be loaded possibly due to other
        --   Roblox servers trying to load this profile at the same time:
        player:Kick("Your data storage profile could not me loaded, please try rejoining.") 
    end
end

----- Initialize -----

-- In case Players have joined the server earlier than this script ran:
for _, player in ipairs(Players:GetPlayers()) do
    coroutine.wrap(FunctionTable.PlayerAdded)(player)
end

----- Connections -----

function FunctionTable.PlayerLeft(player)
    local profile = Profiles[player]
    local start = timeTrack[player]
    timeTrack[player] = nil

    -- Calculate time played:
    local timePlayed = tick() - start
    local roundedTime = math.floor(timePlayed + 0.5)
    local originalsec = profile.Data.secondsPlayed
    local equation = roundedTime + originalsec
    profile.Data.secondsPlayed = equation
    if profile ~= nil then
        profile:Release()
    end
end

return FunctionTable```
checkm4te8 commented 2 years ago

I tried removing ----- Initialize -----

-- In case Players have joined the server earlier than this script ran: for _, player in ipairs(Players:GetPlayers()) do coroutine.wrap(FunctionTable.PlayerAdded)(player) end

and that seemed to help but not fully, sometimes still errors.

checkm4te8 commented 2 years ago

Nevermind, looks like it was caused by another script doing the same, pardon my retardation.