How can I access ModuleScript data from the same ModuleScript in another Script

(Sorry if this is vague, was in a rush)

Hi,

So I’m trying to access Data in a ModuleScript that occurred in the same ModuleScript, but on another Script.

With the Code I have, I essentially create the Data when the Player joins:

Module = require(Data)

Players.PlayerAdded:Connect(function(Player)
    Module.new(Player)
edn)

Within the ModuleScript, new creates a metatable, and then stores it within a table called CurrentTable within the Module table.

module.CurrentData = {}

function module.new(Player)
    local self = setmetatable({}, {__index = {}})

    module.CurrentData[Player] = self
    return self
end

However trying to access the data from another Script it does not work, only printing nil

What could be the reason for this, and how can I fix this?

4 Likes

Can we see how the other script is trying to access the data

3 Likes

use the _G dictionary

--script1
_G["ExampleValue"] = {}
--script2
while not _G["ExampleValue"] do
    wait()
end
print(_G["ExampleValue"])

_G is a table that can be accessed across all scripts
(Client → Client)
(Server → Server)

probably the easiest way.
this is because a module will create a copy of the returned value any time it gets required
unless its from the same script, then you will get the cached result

2 Likes

That doesnt sound like a good idea, considering all the problems, and vunerabilities it has.

2 Likes

I don’t recommend using _G over ModuleScripts for this specific reason:

3 Likes

So Basically, there is a usage of CollectionService that applies .Touched Event, from there it accesses the Player fine, every seems to work as intended, but when atempting to Access the Data on the Script, it returns nil, which ends up causing an error.

The Part of Code is literally just:

local Data = ModuleScript.CurrentData[Player]

It also doesnt work if I create a whole function to gab the Data.

The Data when testing in Empty Baseplates works just fine after remaking the code, however here is for some reason an exception.

2 Likes

That would mean there’s some issue with the surrounding code. Please share.

1 Like

Why can’t you store the created object in a separate ModuleScript?

1 Like

There isnt, it for some reason works after making a complete copy and placing it in an empty baseplate, while in the game im in, just doesnt work

not to mention, both times, it is required at the very beginning of each script, both times happening before the Player even joins the game.

Because it also returns nil, thats the whole issue here.

I copied your setup and things are working completely fine. This is probably an issue with surrounding code as @Anurag_UdayS said.

You’ll have to use a BindableFunction to grab the module environment from a Main script, this is just an example but the way I do it is

function getServerSettings()
	return ServerSettings;
end

function getDataService() 
	return DataManager;
end

local External = Instance.new("BindableFunction");
External.Parent = script;
External.OnInvoke = function(Fnc, ...)
	return getfenv(0)[Fnc](...) 
end

and to use it you’d just need to call External:Invoke(“nameOfTheFunction”);

If I’m understanding this correctly, There seems to be a race condition happening. Whenever you try to access the player data, it hasn’t been created yet, so it returns a nil value. What I normally do with this is create a function that will fetch the cached data instead of accessing the CurrentData directly.

function module.fromCache(Player)
    while not module.CurrentData[Player] and PlayerService:FindFirstChild(Player.Name) do -- Prevent infinite loop if the player leaves.
        task.wait()
    end
    return module.CurrentData[Player]
end

--script
local Data = module.fromCache(Player)
if Data then
    print(Data)
end

You can also use signals instead of task.wait() but nonetheless its still the same.