When creating in Roblox Studio, I am setting up a coin system to store the values of every player. I am doing so, by storing a ModuleScript in ServerScriptService, called “PlayerCoinsModule”. Inside it, you’ll find a table containing how many coins each player has, stored using each player’s User ID as indexes for identification, and the usual functions to alter and read coin amounts. Here is an example:
local PlayerCoinsModule = {}
local PlayerCoins = {}
function PlayerCoinsModule.IncrementCoins(userId, amount)
PlayerCoins[userId] += amount
end
function PlayerCoinsModule.GetUserCoinAmount(userId, amount)
return PlayerCoins[userId]
end
Players.PlayerAdded:Connect(function(player)
local userId = player.UserId
local PlayerCoins[userId] = 0
end)
Players.PlayerRemoving:Connect(function(player)
local userId = player.UserId
local PlayerCoins[userId] = nil
end)
return PlayerCoinsModule
(Note that this is a simplified example, and I am aware it lacks components and best practices. Assume it has all the services available and works perfectly.)
What is the issue?
First, let me contextualize:
When treating a ModuleScript as a source of stored information for the server, whenever I require the Module in question using Server Scripts, the amount of player coins each UserId has attributed to it is always consistent, no matter when I require the module, or in what Server Script I do it.
This is also consistent when doing the same thing in the command line in game by pressing f9 (NOT in studio, this is important)
For example: Let’s say that I create two server scripts and put them in workspace. Let’s say they both require “PlayerCoinsModule”
We’ll call the first script InitialScript, and the second one, ReadScript.
Assuming the userId is for the exact same player in both scripts, let’s check the behavior.
Here is the behavior of InitialScript summarized:
local PlayerCoinsModule = require(ServerScriptService.PlayerCoinsModule)
local userId = Player.UserId
PlayerCoinsModule.IncrementCoins(userId, 5)
Here is the behavior of ReadScript summarized:
task.wait(5)
local PlayerCoinsModule = require(ServerScriptService.PlayerCoinsModule)
local userId = Player.UserId
local value = PlayerCoinsModule.GetUserCoinAmount(userId, value)
print(value)
What happens then? In normal circumstances, even though ReadScript required PlayerCoinsModule 5 seconds after InitialScript did, ReadScript should still print “5”, since InitialScript changed that value for that UserId, and the information should be consistent.
This is the case for me, naturally, when treating ModuleScripts as source of stored information, both in studio and in game.
However, things change when I start using the Studio Command line.
But to contextualize even more, let’s talk about the in-game command line first. Not the studio one.
In-game, by pressing f9, I can run commands, which I personally love to do in order to debug certain elements of the game. Let’s say I want to quickly give the player 100 coins in order to buy an item and test it. I would just run something of the sorts in the command line:
local PlayerCoinsModule = require(ServerScriptService.PlayerCoinsModule)
local userId = Player.UserId
PlayerCoinsModule.IncrementCoins(userId, 5)
(Again, this is a simplified example, pretend it has all the necessary services and components available)
The expected behavior is that it would do exactly what it is meant to do: give the player 5 coins. And that is exactly what it does, IF:
- I require the “PlayerCoinsModule” using another ServerScript
- I require the “PlayerCoinsModule” using not a ServerScript, but the command line in-game, by pressing f9 (which should also run server code)
When does it NOT do that?
- When using the Server-Sided command line in ROBLOX STUDIO
Elaboration: When using the command line in Roblox Studio, I find myself incapable of reading and changing information consistent to the actual game within that module, because it seems that, by running the same debug code example I showed you above in the Studio command line, an alternate version of the “PlayerCoinsModule” seems to be created, where information is completely different, as if the module that was created had never been altered by “InitialScript” in the first place.
Let’s practice the same example of the two ServerScripts, but instead of 2 ServerScripts requiring the module, it will be 1 ServerScript, the InitialScript, and then I will attempt to read the coin amount by using the Roblox Studio Command Line. Let’s hit it:
Here is the behavior of InitialScript summarized, it is the same as before:
local PlayerCoinsModule = require(ServerScriptService.PlayerCoinsModule)
local userId = Player.UserId
PlayerCoinsModule.IncrementCoins(userId, 5)
Here is the debug line that should be ran on Studio Command Line, after InitialScript has done its job:
local PlayerCoinsModule = require(ServerScriptService.PlayerCoinsModule)
local userId = Player.UserId
local value = PlayerCoinsModule.GetUserCoinAmount(userId, value)
print(value)
For some unknown reason, when running this debug line in the Roblox Studio Server-Sided Command Line, even though it has behavior identical to the previously demonstrated “ReadScript”, and also runs Server-Sided, it prints the value “0” instead, as the “PlayerCoinsModule” had never been ever altered in the first place. And it gets worse, if I attempt to alter the values for the “PlayerCoinsModule” using the Studio Command Line, it will treat it as a completely identical copy of the original module, except those changes are only seen by the command line. Example:
If, even after the InitialScript showed above has ran and set the coins for the specified plaver to 5, I run the following code using the STUDIO COMMAND LINE:
local PlayerCoinsModule = require(ServerScriptService.PlayerCoinsModule)
local userId = Player.UserId
PlayerCoinsModule.IncrementCoins(userId, 15)
A weird behavior appears.
After the “InitialScript” incremented 5 coins to that UserId, and the Roblox Studio Command Line incremented 15, Suppose we have the following debug command and want to run it:
local value = PlayerCoinsModule.GetUserCoinAmount(userId, value)
print(value)
The expected behavior is that, since InitialScript added 5 coins, and then the Studio Command Line added 15, no matter where I run those 2 lines, as long as it’s Server-Sided, it should print 20. However this is not the case.
- Running the 2 demonstrated debug lines in Studio Command Line, prints “15”
- Running the 2 demonstrated debug lines in any Server Script, prints “5”
I do not understand why this is happening, given that the in-game f9 command line works properly, and that doing the same thing with ServerScripts also results in expected behavior. It is as if the Roblox Studio Command Line has a completely different behavior. Am I doing something wrong? Am I treating modules incorrectly? Is there any “fine print” of sorts that I am not aware of? I know that ModuleScripts will only run the first time you use “require()” them and will return what they first returned afterwards, yes, however, I am sure the information altered within variables there should be kept consistent thorough the server. This is how I have been building my structures to store player information. Am I wrong and doing this incorrectly? Or is this a very specific bug/unwanted conditional behavior that I have found?
TL;DR: Why does requiring (Server-Sided) ModuleScripts from the (Server-Sided) Studio Command line create a replica of the (Server-Sided) ModuleScript, while requiring it anywhere else (Also from the Server Side), including the f9 command line, does not?
Things to be kept in mind
- I am completely aware that different versions of a module script existing is expected behavior IF you require it from the server, and require again from the client. This is never the case, as my example Module is in ServerScriptService. The issue described here arises only when requiring a module using the Studio Command Line. In the issue described here, the module is always required by the server. The client is not involved in this issue, therefore the client and its replication are irrelevant to the topic.
- I am also completely aware that the Studio has two command lines, one for running server sided code, and one for running client sided code. The issue described arises when running server sided code, and once again, the client is not involved. As a matter of fact, the debug lines presented here would not even run if they were to be executed in the client, as it cannot access the module that is in ServerScriptService.
Thanks in advance!