Player is nil in Module Script?
Boom boom complicated metatables ahead!
Great, I'm inexperienced in writing questions for I have only written answers, ain't that dandy?
My issue is that whenever I try to access the player in a module script, it thinks it's nil, here is the source code
01 | local DS = game:GetService( "DataStoreService" ):GetDataStore( "Stuff_DS_V1" ); |
03 | PM.RegisteredPlayers = { } ; |
06 | Methods.GetData = function (plr, key, defaultVal) |
07 | local data = DS:GetAsync(plr.player.userId.. "_" ..key); |
09 | if type (defaultVal) = = "table" then |
19 | Methods.SaveData = function (plr, key, val) |
20 | DS:SetAsync(plr.Player.userId.. "_" ..key, val); |
23 | Methods.LoadData = function (plr) |
24 | local data = plr:GetData( "Stats" , { Blox = 0 , Lvl = 1 , Exp = 0 } ); |
28 | local backpack = plr:GetData( "Backpack" , { Backpack = { "Sword" , "Classic" } , Equipped = { Melee = "Sword" ,Grave = "Classic" } } ); |
29 | for i,v in pairs (backpack.Backpack) do |
30 | table.insert(plr.Backpack, v); |
32 | for i,v in pairs (backpack.Equipped) do |
33 | plr.Equipped [ tostring (i) ] = tostring (v); |
37 | Methods.Destroy = function (plr) |
38 | PM.RegisteredPlayers [ tostring (plr.player.userId) ] = nil ; |
41 | PM.RegisterPlayer = function (plr) |
42 | if PM.RegisteredPlayers [ tostring (plr.userId) ] = = nil then |
50 | __index = function (tab, key) |
51 | if key:lower() = = "player" then |
53 | elseif Methods [ key ] then |
55 | return Methods [ key ] (...); |
60 | print ( "ERROR: " ..key.. " is nil." ) |
64 | PM.RegisteredPlayers [ tostring (plr.userId) ] = Data; |
67 | print (plr.Name.. " is already registered and will be allowed to access the custom methods." ); |
68 | return PM.RegisteredPlayers [ tostring (plr.userId) ] ; |
72 | PM.Get = function (plr) |
73 | if plr = = nil then print ( "Argument 'plr' is nil." ) return ; end |
74 | print ( "Getting the Player Table for: " ..plr.Name); |
75 | return PM.RegisterPlayer(plr); |
That is the module script, as you can see, if the index is "player", then it returns the player object
And this is the normal handler script
01 | local PM = require(game.ServerScriptService:WaitForChild( "Modules" ):WaitForChild( "PlayerManager" )); |
03 | game.Players.PlayerAdded:connect( function (plr) |
04 | local makeshiftPlayer = PM.Get(plr); |
05 | print (makeshiftPlayer.Player.userId); |
06 | makeshiftPlayer:LoadData(); |
09 | game.Players.PlayerRemoving:connect( function (plr) |
10 | local makeshiftPlayer = PM:Get(plr); |
11 | makeshiftPlayer:SaveData( "Stats" , { Blox = makeshiftPlayer.Blox, Lvl = makeshiftPlayer.Lvl, Exp = makeshiftPlayer.Exp } ); |
12 | makeshiftPlayer:SaveData( "Backpack" , { Backpack = plr.Backpack, Equipped = plr.Equipped } ); |
14 | makeshiftPlayer:Destroy(); |
But what's interesting is, the error only happens when a player leaves, I've already tested if the player is nil if you send it to a module, it is not.
The very error happens in the PM.Get function, which isn't even all that complicated, but even the script can't find the player for some reason.
11:49:06.526 - ServerScriptService.Modules.PlayerManager:74: attempt to concatenate field 'Name' (a nil value)
11:49:06.527 - Stack Begin
11:49:06.529 - Script 'ServerScriptService.Modules.PlayerManager', Line 74 - method Get
11:49:06.530 - Script 'ServerScriptService.Scripts.Player', Line 10
11:49:06.531 - Stack End
If I remove the 'print("Getting the Player Table for: "..plr.Name)', it errors in the Methods.SaveData function, where it says userId is nil.
11:49:06.526 - ServerScriptService.Modules.PlayerManager:68: attempt to concatenate field 'userId' (a nil value)
11:49:06.527 - Stack Begin
11:49:06.529 - Script 'ServerScriptService.Modules.PlayerManager', Line 68 - method SaveData
11:49:06.530 - Script 'ServerScriptService.Scripts.Player', Line 11
11:49:06.531 - Stack End
And, like the other error, it only errors when you leave. I suspected that when you index 'player' it returns nil since the player left.
How can I access the player, without it being nil?