Im using profile service for my inventory saving system, I have an EquippedWeapons key which stores the player’s equipped weapon. When the player joins, I have a server script that get the Equipped weapons but I’m getting “Attempt to call a table value” error
-- part of the code that is revelant, is inside a player added function
local equipped = PlayerDataHandler:getEquippedWeapons(plr) -- this function is erroring
char:SetAttribute("CurrentWeapon", equipped[1])
plr.CharacterAppearanceLoaded:Connect(function(char)
local weaponName = char:GetAttribute("CurrentWeapon")
local Weapon = WeaponModels[weaponName]:Clone()
This is the playerdatahandler module here is some of the relevant functions
function PlayerDataHandler:getEquippedWeapons(plr)
local equipped = PlayerDataHandler:Get(plr, "EquippedWeapons") -- Get called here
return equipped
end
local function getProfile(plr)
local profile = Profiles[plr]
if not profile then
profile = { Data = dataTemplate() } -- attempt to call a table value error here
Profiles[plr] = profile
end
return Profiles[plr]
end
function PlayerDataHandler:Get(plr, key)
local profile = getProfile(plr) -- get profile called here
assert(profile.Data[key], string.format("data does not exist for key: %s", key))
return profile.Data[key]
end
are you referring to dataTemplate()? Sorry I only understand Profile Service on a very surface level, i know how to make the functions for changing my different datas but I dont really understand how it saves data since I made it while watching a tutorial
Well the issue here is that dataTemplate is a dictionary, not a function.
In your line profile = {Data = dataTemplate()}, those parenthesis mean the code is trying to run a function declared dataTemplate and assigned the returned value to Data, not the dictionary itself like you’ve shown.
It was working up until I was trying to find a work around to use the :Get function inside of a script outside of PlayerDataHandler. If this is the case then how should I find a work around that wont interfere with whatever GetProfileStore does?
I’m not exactly sure what you mean, but overall I think your logic approaching this is flawed.
local ProfileStore = ProfileService.GetProfileStore(
"PlayerProfile",
dataTemplate
)
Should only be declared once somewhere at the top of your module.
When the player joins, hook a function via Players.PlayerAdded
The function will then attempt to load the player’s profile by doing:
Players.PlayerAdded:Connect(function(player)
local profile = ProfileStore:LoadProfileAsync(
"your_profile_name_here",
"ForceLoad"
)
--> "your_profile_name_here" defines exactly what saved data we want, and it is a mustthat
-- that you include the player's UserId for a unique key. ex: "Player_Data_"..player.UserId
-- "ForceLoad" is a means of retrieving the profile, and I advise you read ProfileService's API
-- documentation for further information
if not profile then
player:Kick("Could not retrieve profile. Please rejoin.")
return
else
PlayerDataHandler.Profiles[player.UserId] = profile
--> do other logic with your loaded profile here, such as
-- hooking a profile:ListenToRelease() function
end
end)
function PlayerDataHandler.GetProfile(player)
return PlayerDataHandler.Profiles[player.UserId]
end
-- accessing a profile from another server script
local profile = PlayerDataHandler:GetProfile(player)
local playerData = profile.Data
Essentially what we’re doing is attempting to load the player’s profile, via ProfileStore:LoadProfileAsync(), and if it does not return a profile (data stores may be down) then simply kick the player from the game, since we do not want to let the player in the game if there are active issues with DataStoreService.
Do note that when indexing the player’s retrieved profile in PlayerDataHandler.Profiles, do not assign profile.Data, but the profile itself because we want to be able to release the profile when the player leaves the game (profile:Release()), and this cannot be done if the player’s profile data is returned from PlayerDataHandler.GetProfile() instead of the actual profile itself.
Here is the official ProfileService API for more information: API
Yes this is all done I didnt include everything in my script because it would be too long but now that you mention my flawed logic i have no idea why I though I couldnt call Get from a script but thank you for your time dealing with my bad case of tunnel vision
I was able to use simply use “:Get” to get the data the problem probably lies with this function that I didnt put much though into
Instead of having a whole separate function to get the player’s equipped weapon, you could just do
local profile = PlayerDataHandler.GetProfile(plr)
local equippedWeapons = profile.Data.EquippedWeapons
Or if you must,
function PlayerDataHandler.GetKeyValue(plr, key)
local profile = PlayerDataHandler.GetProfile(plr)
return profile.Data[key]
end
-- accessing equipped weapons from another script
local equippedWeapons = PlayerDataHandler.GetKeyValue(plr, "EquippedWeapons")
Ultimately your PlayerDataHandler.GetProfile() (defined as :Get() by you) function should be no longer than one line which returns the loaded profile that was previously indexed to PlayerDataHandler.Profiles in the PlayerAdded function. The code below in your current function is unnecessary.
if not profile then
profile = {Data = dataTemplate}
Profiles[plr] = profile
end
yeah im sorry I just realized there was alot of things I didnt mention which probably caused you alot of confusion
this was my :Get function I was mentioning earlier
function PlayerDataHandler:Get(plr, key)
local profile = getProfile(plr)
assert(profile.Data[key], string.format("data does not exist for key: %s", key))
return profile.Data[key]
end
local function getProfile(plr)
assert(Profiles[plr], string.format("Profile does not exist for %s", plr.UserId))
local profile = Profiles[plr]
if not profile then
profile = { Data = dataTemplate() }
print(profile)
Profiles[plr] = profile
end
return Profiles[plr]
end
I also appreciate that your explaining me what each function does because I really need to learn it so I wont have as much trouble next time