I’ve recently come up with a system where all client and server scripts have a Central Module that contains vital information for the server and local settings for the client. This centralised system is a method for the whole machine to communicate with it’s components all in one module, although I’m a little skeptical with this idea, because it would make exploits easier in a scenario where I fail to implement the proper security measures, although there should be a separate security system independent from the module to check any suspicious player activity.
The Setup
Client Sided
Reference:
Client Control
Client control is a module that contains different settings and permissions managed by the client. Inside of the module script, you will find some example scripts.
1.1 Use Cases
Permissions
From the name “sprint”, the puspose of this local script is obvious. Sprint uses the client control to determine whether the player is allowed to sprint or not using functions like ClientControl:GetLocalPermissionState("Sprint") and can be changed with ClientControl:SetLocalPermissionState("Sprint", false)
Example
if ClientControl:GetLocalPermissionState("Sprint") == true then
--code to sprint
elseif ClientControl:GetLocalPermissionState("Sprint") == false then
--code to walk
else
--throw warning
end
Settings
The script Chat Bubble Color (purpose obvious from the name) gets the color for the chat bubbles set by the player with this function ClientControl:GetLocalSettingsState("ChatBubbleColor") and can be changed with ClientControl:SetLocalSettingsState("ChatBubbleColor", "Dark")
Example
if ClientControl:GetLocalSettingsState("ChatBubbleColor") == "White" then
--code to make chat bubbles white
elseif ClientControl:GetLocalSettingsState("ChatBubbleColor") == "Dark" then
--code to make chat bubbles dark
else
--throw warning
end
1.2 Security Issues
The module can be accessed by the client’s machine in the event of an exploit, given the right tools, the exploiter can modify the settings/permissions inside of the module. In the future, the server will be able to check on the module to see any unauthorized changes and decide whether it was caused by accident or an exploit.
Server Sided
Server Control
I haven’t made a module for a server yet, simply because I don’t see a need for one yet.
Thoughts?
Please tell me what you think about this system, I’d really appreciate it
I do not understand what problem you are solving with this. The client can modify anything stored in its memory, and it’ll be nigh impossible to validate using the server. (since the client can circumvent mostly any type of check)
The only real comment I can think of is a desire to centralise everything is often an omen for large and cluttered modules full of functionality that’s easier to debug if it was in separate modules/scripts.
This module is just to store states of objects on the client. Like let’s say if the player is in a cut scene, instead of making another script to disable movement, you can just do ClientControl:SetLocalPermissionState(“Movement”, false). The server would get a copy of this information and whenever the server would check to see if this information is still true or not, it would make the necessary actions.
This module is not a bridge to making exploiting easy. This module just holds any information that any exploiter can modify outside of the module itself (Walk speed for instance). The server will always have it’s own security system independent from the module to check if the client is doing something off norms.
In addition:
The problem I am trying to solve is to connect all the client data into one module to make client sided scripts and ui easy to sync.
Whether or not this is a good idea depends on how literally you mean “all the client data”. Your examples suggest you’re envisioning one singleton data model for every system in the game, which is basically the global variable anti-pattern, a known road-to-ruin. You end up with your program having a zillion variables that collectively represent some implicit state, but it’s not a state you can easily validate. You end up with spaghetti code and bad state bugs pretty quickly.
It’s completely acceptable to make separations of data model and the visual components on the client that consume the data (e.g. a Model View Controller pattern), but this pattern does not just mean all your game data just goes in one big bucket, you still want to organize data logically into game subsystems, with interfaces for validation, encapsulation, etc. What it entails is decoupling how the data is stored from how it is modified and displayed, so that you can do something like re-invent your UI without having to refactor the underlying data model.
Thank you for the insight
If this is the case, I guess that would mean that making player data/variables harder to find would be the proper way? Or not really, it’s just really a bad idea?
It’s not worth shooting yourself in the foot for fancy code or some meaningless advantage. In the end, the code only matters to you and your collaborators. Players are only going to be playing your game. Productivity > code aesthetic.
I really don’t, because I never make any effort at all to put anything on the client. I focus on securing my game and being productive in how much content I release over paying petty exploiters any heed.
Being aesthetically pretty about your code doesn’t hurt, but it’s only a technical advantage while you’re developing. The end user isn’t going to see your code, they’ll only see the game. Just don’t go overboard because it’s not worth hampering your development in the future over “obscure variables” or whatever.
No. I have a respective distribution between my server and client environments and networking where necessary. The difference is that I don’t make any effort to combat exploiters via their own client. All my security exists on the server.
Client input is a contextual thing. Most of the time it’s not me explicitly checking for what the client is sending, but making a catch-all for receiving input. Sometimes, the client may need authority for situations where what they do only affects them but needs something on the server (e.g. editing their keybinds to be saved).
For example; you have a tool system where you need to press E to change modes. I don’t check explicitly for if E was pressed, I check for if the client requested for the action associated with E. Client would say “E is pressed, okay server please change modes”. Server would say “a change mode request, hm, does the client meet my demands?”
…by input, you mean something like this, right? I hope I didn’t misinterpret your question.
What you said is related, but I meant like raw data (not sure if that was the right term) input like sending a client sided part’s position, color, what the client sees, etc.
That depends on the use case. I don’t find myself often having to transfer data in this manner.
On a separate note, if you’d like, you can begin a new thread or DM for these kinds of validation concerns (but be concise, since there’s already tons of threads on it). Seems we’re branching away from the whole centralised control script idea.