ModuleScript not retaining table data

I am creating a tycoon kit (yes, I know) and I am trying to add memory for what buttons the player has pressed in their tycoon. At the moment, I have a MemoryModule which works like so:

local Module = {}
local ButtonMemory = {}
local ButtonsFolder = script.ButtonsFolderReference.Value

---------------------------------------------------------
--       Note about ButtonMemory: Order Matters        --
-- Keep this in mind when using or modifying the array --
---------------------------------------------------------

-- Adds a button id to the memory
Module.AddButtonMemory = function(id)
	ButtonMemory[#ButtonMemory + 1] = id
end

-- Sets all the button ids
Module.SetButtonMemory = function(tbl)
	ButtonMemory = tbl
end

-- Returns all button ids in the memory
Module.GetButtonMemory = function()
	return ButtonMemory
end

-- Takes all the memory for this tycoon and applies it as nessecary
Module.ApplyMemory = function(Player)
	-- Apply button memory
	local Buttons = ButtonsFolder:Clone():GetChildren()
	for i,bid in ipairs(ButtonMemory) do
		for j,v in ipairs(Buttons) do
			if (v.Value.Configuration.Id.Value == bid) then
				require(script.ButtonModuleReference.Value)(Player, v.Value, true)
				table.remove(Buttons, j)
			end
		end
	end
end

return Module

Basically, when a button is pressed it will call Module.AddButtonMemory with the ID of the button that was pressed. This will add the button to the end of the table which will end up saving both the ID of the button and the order in which the button was pressed as compared to the previous buttons. This is what I need to be saved.

Eventually, our DataStore managing script will come along to require this script and call Module.GetButtonMemory. It works like so:

Module.Save = function(Player, Attempts)
	-- ...
	local MemoryModule = require(Tycoon.Scripts.MemoryModule)
	local DataButtons = MemoryModule.GetButtonMemory()
	-- ...
end

(The SetMemory function is only called when loading save data the second they claim the tycoon and works properly)

The issue comes into play when we get the memory. For some reason, the DataButtons is completely empty!

I’ve added print statements in the AddMemory function, the DataStore manager, and the ButtonScript that adds the button id. Everything works properly (that is, the buttons are stored in the memory) all the way up until the DataStore manager attempts to call GetButtonMemory. The table is completely blank!

All of the related scripts are server scripts and/or module scripts, so they should be running on the server.

Here is a video describing the functionality and the issue: 2021 04 12 21 54 42 - YouTube

Any ideas what could be causing the issue? Let me know if you need more information!

EDIT: I have found that this issue only occurs when running the following line of code ON THE SERVER in Studio’s console:

require(game.ServerScriptService.DataManager).Save(game.Players.FireController1847)

It works fine when the internal DataManager calls the save function. I have no idea why this could be the case.

1 Like

The context of the console is not within the running game, so I’m not sure if the console issue is related.

I can’t tell if what you’re expecting from the ModuleScript(s) is reasonable, for lack of context.

Can you give more info?

2 Likes

Are you calling your save functions on the server and the load functions on the client, or vice versa?

Can you provide a minimal example that fails?

Well, the issue actually only happens when calling it from the console, so that may be the primary reason. Sorry if I didn’t provide enough context, I tried my best. Unfortunately there really isn’t much more info I can give other than posting the entire DataManager script alongside the touch for the door.

This is the minimum example I can think of at the moment. I think like Club_Moo said it is only related to the fact that console does not run in the same context as the game (?) so that may be the issue. It works fine when using it normally.

So you’re saying that the only time it fails is a test from from the console?
If so, maybe there is no problem.
Some of my “concerns” of the rest of the situation, and wanting to see more, have to do with:

  • If there is proper handling of multiple players
  • If there are any incorrect assumptions about how ModuleScripts function
  • If there were any assumptions made about the nature of replication, eg. what is and isn’t
  • If there were any incorrect assumptions as to how things function, eg. clone
  • If there were any incorrect assumptions about RemoteEvents
  • If there is any confusion about tables versus objects
  • If there are any issues with lack of WaitForChild() use

I mean, it would be preferred if we were able to save from console for testing purposes, but I suppose we can get around that with some testing buttons or just adding autosaving haha. I appreciate your responses!

I totally understand your concerns and I think I can answer all of them:

  1. It does properly handle multiple players because this script is individually cloned for each tycoon which can only have one player at a time
  2. I know that ModuleScripts are supposed to be, well, modular, but it can also allow for other scripts to require it and call functions that can modify an internal memory. I’m basically using it like a cache
  3. I’m not sure I understand what you mean by this
  4. I clone because I remove the doors to improve the speed of the searching algorithm (no need to search through ones we’ve already found again), so I make a temporary clone to remove items from it. Once we’re done searching (and subsequently calling the buttons to purchase), the memory of the clone should (theoretically) be released
  5. I don’t use RemoteEvents here, everything is ServerSide
  6. No, there isn’t. The MemoryModule contains an array of button IDs. The position of the button ID in the array is the order in which the buttons were pressed. I am using the table as an array.
  7. I have yet to find any. Everything the script refers to is created by the time the script is called.

Let me know if you have any other questions.

Try using the dev console in studio with F9 and running the same line of code. That will run your code as level 2 whereas running from the console runs in level 4 I believe, so I think @Club_Moo is correct. The console always runs in a higher security level than regular scripts and modules required from regular scripts and as far as I am aware requires are unique for every security context.

Regarding Clone()s–Actually I was mentioning ones potentially in other code not shared.
But since you mention it, if you are referring to ButtonsFolder:Clone()… It looks to me
like this clone isn’t even necessary (unless you’re trying to do some sort of snapshot?)
Also I would urge you not to use table.remove(), especially not on a table you’re iterating,
and especially not when in a forward direction. I’d suggest reworking it. (It may be not horrible here,
if we’re talking about a very small table, but table.remove() should generally be avoided.)