Player = nil in module script. Why?

I am trying to pass the player into a module script to send some information to my server.

I am using a server script, and passing information into a ‘server’ module.
When I pass the player into the parameters, the player is nil on the other side (the server module)

Server Script:

local serverMods = require(game:GetService("ServerScriptService").Modules.ServerModules)
print (player, player.Name) -- prints my players name
local result = serverMods:SavePlayerLeaderStats(player, stage, timeLaps);

Module Script:

function module.SavePlayerLeaderStats(player, stage, completionTime)	
print (player, player.Name) -- prints nil
end

I’ve tried doing some basic debugging, and searched the forums/google for a similar issue, but found no answers so far. I’d thought of just sending the player name, rather than the player; but I’d like to omit unnecessary extra code if possible, and I like to know why things don’t work :slight_smile:

What could the issue be?

Thank you for reading
Regards!

1 Like

It’s because you cannot define the local player in server scripts(including module scripts)

Actually, I disagree.

To keep this simple, I’d say a module script acts like the script that requires the module. If only LocalScripts are requiring the module, having the local player as a variable or defining it would be fine. On the other hand that would error when attempting to require the module with a ServerScript.

Thank you for replying
The server script does not send localPlayer; player is gathered this way:

touchPart.Touched:Connect(function(hit)
	
	local player =  game.Players:FindFirstChild(hit.Parent.Name);
	if player ~= nil then 
-- do some stuff
end
end)

Thank you for replying.

A single module containing both server and client commands will work regardless of where the module is being called (Server or local scripts); its the code contained in the module that would be conflicting. That said, obviously, server modules would be stored on the serverscriptservice, as to avoid exploiting; and thus no local script could call it anyway. That is, if you care about the content within your script being secret.

How are you calling that module function? Are you using . or :?

5 Likes

I was using :

Replacing it with ‘.’ has solved my issue. But I don’t understand why.

The reason you were having this problem is because using : is “syntactic sugar”. Under the hood, using a colon injects the table itself as the first argument.

For instance:

myModule:Test(32) is exactly the same as myModule.Test(myModule, 32)

As such, defining a function on a table can be written like this:

function myModule:Test(num) is the same as function myModule.Test(self, num). In that first example, self is injected as the first argument implicitly.

8 Likes

Is that how OOP works? (I’m very interested in learning in OOP). Could you explain the difference between using : or . in creating functions?

EDIT: I’ve read many many topics on OOP but never understood them.

Check out this thread: All about Object Oriented Programming

4 Likes

Yes and no. Lua does not have actual OOP, but you can come close enough using metatables. Lua does not normally have a self or this keyword, so : was added to cover the missing functionality. As @Crazyman32 said, : calls the function with the table as the first argument. Using metatables, we can create class functions like you would in other languages.

local class = {}
class.__index = class
-- if you want this class to get the functions from another class, add this next line
-- setmetatable(class, inheritanceclass)

function class:doSomething()
  -- self is now defined
  self.foo = "bar"
end

function class.new()
  local newobject = {}
  setmetatable(newobject, class) -- now if we call a function on the new object, it will look for __index in the metatable, find it pointing to class, then look through class for the function
  return newobject
end

local object = class.new()
object:doSomething()
print(object.foo) --> bar
3 Likes