Storing a array/dictionary question

Alright, I’m currently trying to create a moderation service, currently I’m making the system that handles warning uses, every user is going to have a table of their warns like so

local Table = {

["ClientScripts"] = {"ReasonForWarn","DateOfWarn","ModeratorWhoWarned"}


}

Now this table needs to be updated whenever a moderator called the !warn player command on that player, however, I’m not sure where I should store the table because A. It needs to be updated and used by our DataStore and the warn function.

I’d just use the table as a handler, and save all of the tuple data in the Server Script if that makes any sense. Basically run a check (if they are at the warning limit, do whatever) if not get ClientScripts[1], ClientScripts[2], and ClientScripts[3] and store those in your datastore, update them to whatever GUIs you have, etc.

I remember I was stuck over the issue of saving a table for like a week or something. I eventually used _G, but I don’t know how well that would work in a major game.

Maybe try using module scripts with a function that would add something to an array, then another function that would return it?

I highly recommend against using _G in any script, it just starts cluttering up global variables and makes things slower overall.

If your admin system is all in one script (like Basic Admin Essentials for example), you can just declare the dictionary as a local variable in the script. If you’re going for a modular based system, you should try to declare the dictionary as one of the variables inside the module.

For example, inside a ModuleScript:

local module = {}

module.ClientScripts = {"ReasonForWarn","DateOfWarn","ModeratorWhoWarned"}

You can then require the module and update the values through a function or manually. IIRC the module information will not update automatically and will need to be re-required every time you want updated dictionary info. Please correct me if I’m wrong on this.

2 Likes

Huh? What’s your source for this? I know several scripts and such that use _G. I’ve never understood what the whole dislike about _G is. The framework I use, Aero Game Framework, has it. Slowdowns are not at all a problem and neither is clutter.

1 Like

Many developers declare global variables in a way that would be easy for the developer of the framework to read. These variables, although not always, can also come upon the minds of the developers using that framework. Now if these two global variables are suddenly declared in two different scripts, one is bound to overlap another. Add in some loops and events and you have a constant volley of overwriting that single value. What’s the result? A framework that expects one value but gets an overwritten value and code that expects a value but gets a value given by the framework developer.

I usually don’t have a problem with having global variables whose value is a strong or a number as they don’t get cluttered as easily. However, when you start adding in dictionaries, arrays, and other tables, it creates more of a chance for developers to make a mistake at properly ensuring that the table is maintained and does not get cluttered. However, once it does start getting cluttered, you have to deal with all scripts in a game having a harder time to process everything instead of having only one script with local scope variables dealing with cluttered tables.

Edit: If you are looking for a source on this, I find it easy to just look up why global variables are frowned upon in any language, be it Python, JavaScript, or Lua. The concepts are more or less the same in each language.

2 Likes

The first case just sounds like blatant failure to address what can be fairly obvious implementation flaws. For the framework I’m using, AeroGameFramework, it reserves a single “namespace” in _G (_G.Aero). There’s an almost zero chance of any of that overlapping nonsense. There’s one bootstrapper that sets everything up and every other variable waits for the strapper to assign _G.Aero rather than trying to declare.

Repository if you’re interested and don’t have the link:

I think _G on Roblox still has use so long as you address what can be fairly obvious issues. That’s as far as your own code goes though. On the other hand, I completely agree with the point you’re raising. _G can get especially troublesome for OSS that doesn’t appropriately sort their resources and dependencies (e.g. like Aero, having a single table represent all of the framework’s globals).

To elaborate on the above a bit: as far as Roblox goes (since I do know there’s the whole “no to global variables” with other languages), it’s completely fine if your software defines a table within _G and then uses that for any global variables.

_G.MyFramework = {
    Something = {},
    OrTheOther = {},
}

-- or

local MyFramework = {
    Something = {},
    OrTheOther = {},
}

_G.MyFramework = MyFramework

What starts becoming painful is if there’s a lack of sorting and code hogs the first dimension of _G.

-- The readability on this is terrible anyway
_G.Something = {}
_G.OrTheOther = {}

As for _G in general being global, you could assign your corner of dependencies over to a local variable. That would dismiss the whole global argument, would it not?

local MyFramework do
    while not _G.MyFramework do wait() end
    MyFramework = _G.MyFramework
end

Please do point something out if I’ve made a disagreeable remark, I’m sort of just volleying ideas here since I never genuinely understood the _G war for Roblox. For other languages it may be a different story but Roblox essentially takes the development process and greatly simplifies it, which is why I find that _G on Roblox is fine so long as it doesn’t become habit in other languages.

All in all though, if you have a framework, you don’t have much use for _G, since your strapper would be requiring modules and sending your tables and such to modules from a main source point. The only reason you’d actively need _G is for external script access which botches the idea of single-script architecture.

2 Likes

I find your points completely valid, if the global variables are used it should be fine. Just speaking for the beginner scripters that may not know as much information, especially since declaring a global value in Lua can be as easy as a = 1 without having to touch _G at all.

I know in my past I’ve probably been doing stuff like NewTable = {} or SomeNumberVariable = 1 without defining the local scope and completely disregarding it, especially when I was a beginner and I didn’t know any better about scopes. The issues I’ve mentioned before also come up more often here, having an easy to remember variable name like, I don’t know, Part or Door or something like that. These names can someones appear in more than one script and subsequently cause issues with the value of that global key.

After realizing the importance of scopes, I’ve just in general discouraged the use of global variables if it can be avoided but I recognize that if it can be used properly then there shouldn’t be any issues with using it.

2 Likes

Since this was only a week ago and on the same topic, I guess I’ll ask here.

I’m trying to store a table on the client in a module script. The table is fired from the server using an RE but that part works fine. For some reason the first function works, but the second one says the inventory is nil. Could anyone help?

image

local module = {}
module.inventory = nil

module.GotInventory = function(newinv)
	print("got inv")
	module.inventory = newinv 
	print(module.inventory)
end

module.GetInventory = function()
	print(module.inventory)
	if not module.inventory then
		warn("(Client) Waiting for inventory...")
		repeat wait() until module.inventory
	end
	
	return module.inventory
end

return module