I have a module for storing player stats called PlayerData. The module is made for created objects following the model described in All about Object Oriented Programming - Resources / Community Tutorials - DevForum | Roblox
When a player joins the game, I attempt to load their data from a DataStore. If nothing is loaded, a new PlayerData object is created for them. That object(table) is what gets saved to the DataStore. Through the DataStore Editor plugin I can see that saving this data works for saving the data defined in the PlayerData.new function.
My issue is that I get the PlayerData objects through a bindable function but when I try to call a function from it I get “Attempt to call missing method “IncreaseDefense” of table.” Values defined in PlayerData.new can be referenced without issue. I set the metatable of the table created by PlayerData.new as it is done in the above post, so I do not understand why the functions cannot be found. Any assistance would be appreciated
PlayerData module
local PlayerData = {}
PlayerData.__index = PlayerData
-- Create new PlayerData object
function PlayerData.new()
local self = setmetatable({}, PlayerData)
self.strength = 3
self.defense = 0
self.speed = 0
self.strengthOnClick = 1
self.defenseOnClick = 1
self.speedOnClick = 1
return self
end
-- Get total power as combination of 3 primary stats
function PlayerData:GetTotalPower()
return self.strength + self.defense + self.speed
end
-- Increase strength by strength on click value
function PlayerData:IncreaseStrength()
self.strength += self.strengthOnClick
return self.strength
end
-- Increase defense by defense on click value
function PlayerData:IncreaseDefense()
self.defense += self.defenseOnClick
return self.defense
end
-- Increase speed by speed on click value
function PlayerData:IncreaseSpeed()
self.speed += self.speedOnClick
return self.speed
end
return PlayerData
Script handling loading/saving data and bindable function
local DataStore = game:GetService("DataStoreService"):GetDataStore("UnlimitedPower")
local data = {}
local PlayerData = require(game:GetService("ServerScriptService").Modules.PlayerData)
local BindableFunctions = game:GetService("ServerStorage").BindableFunctions
game.Players.PlayerAdded:Connect(function(player)
-- Get Player id
local id = "Player_" .. player.UserId
-- Load data
local success, errormessage = pcall(function()
data[id] = DataStore:GetAsync(id)
end)
if(data[id] == nil) then
data[id] = PlayerData.new()
end
print("Strength: " .. data[id].strength) -- Prints 3
end)
game.Players.PlayerRemoving:Connect(function(player)
-- Get Player id
local id = "Player_" .. player.UserId
-- Save data
local success, errormessage = pcall(function()
DataStore:SetAsync(id, data[id])
end)
-- Remove from data table
data[id] = nil
end)
BindableFunctions.GetPlayerData.OnInvoke = function(player)
local id = "Player_" .. player.UserId
return data[id]
end
Script attempting to get PlayerData object and call functions
local RemoteFunctions = game:GetService("ReplicatedStorage").RemoteFunctions
local BindableFunctions = game:GetService("ServerStorage").BindableFunctions
-- Strength button function
RemoteFunctions.StrengthClick.OnServerInvoke = function(player)
local PlayerData = BindableFunctions.GetPlayerData:Invoke(player)
print(PlayerData.strength) -- Prints 3
end
-- Defense button function
RemoteFunctions.DefenseClick.OnServerInvoke = function(player)
local PlayerData = BindableFunctions.GetPlayerData:Invoke(player)
local newDefense = PlayerData:IncreaseDefense() -- "attempt to call missing method 'IncreaseDefense' of table"
print("Defense: " .. newDefense)
return newDefense
end
-- Speed button function
RemoteFunctions.SpeedClick.OnServerInvoke = function(player)
local PlayerData = BindableFunctions.GetPlayerData:Invoke(player)
local newSpeed = PlayerData:IncreaseSpeed() -- "attempt to call missing method 'IncreaseSpeed' of table"
print("Speed: " .. newSpeed)
return newSpeed
end