Hello, I have been a programmer for a while but I tried to start modularizing my code not too long ago and I have run into some issues ever since.
at the moment I am trying to make a modular baseball bat system but I am unsure about what I should do next, what I mean is I know how the logic should work on the server side but I am very confused about how the code should work on the client
I am aware of how remote events work, but I’m not sure about how to integrate them with a module script. This is the code I have written so far:
local BatModule = {}
BatModule.__index = BatModule
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Modules = ReplicatedStorage.Modules
local Remotes = ReplicatedStorage.Remotes
local Bats = ReplicatedStorage.Bats
function BatModule:_new(bat: Tool, ...)
local self = setmetatable({}, BatModule)
self._bat = bat
self._config = require(bat:FindFirstChild("Config")) or {}
self._cooldown = false
return self
end
function BatModule:_swing()
if self._cooldown then
return
end
self._cooldown = true
end
return BatModule
Nice start! You have the fundamental knowledge of what to do already, one of the ways to go about it is to create a CLIENT version of the baseball bat object which handles all client-side related stuff. I do this for a lot of my objects; I’ll have a SRV_Object and CL_Object that handle logic for the respective context.
Could this work? I’m aiming to make the system very modular
local BatModule = {}
BatModule.__index = BatModule
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Modules = ReplicatedStorage.Modules
local Remotes = ReplicatedStorage.Remotes
local Bats = ReplicatedStorage.Bats
function BatModule:_new(bat: Tool, ...)
local self = setmetatable({}, BatModule)
self._bat = bat
self._config = require(bat:FindFirstChild("Config")) or {}
self._cooldown = false
self._isServer = RunService:IsServer()
return self
end
function BatModule:_swingServer()
if self._cooldown then
return
end
if not self._isServer then
return
end
self._cooldown = true
end
function BatModule:_swingClient()
end
return BatModule
Wow that was a very fast reply, I’ll assume you already had it prepared haha
And yes there are two ways here:
Create a new ModuleScript for the client and the server version.
Share the same ModuleScript for both client and server.
Pros: Can share properties & methods
Cons: Could potentially be a little confusing with everything in the same script
Ultimately it’s up to you. Within the _new() method you could check for the script context using RunService:IsClient() and RunService:IsServer() and then bind your necessary RemoteEvents depending on the result.
Yeah I was just about to edit the message, but what way would you go about it?
also I did think about making 2 folders, 1 for client modules and the other for server modules
the client could just handle the client sided logic (visual feedback, input and etc) and the server can handle the real logic (damage, knockback and so on)
I’m just lost on deciding which one is the best choice
I’m afraid there isn’t particularly a “best choice” here, at least one that isn’t subjective. But I’d personally recommend splitting server & client versions of modulescripts.
Another pro for splitting server & client modulescripts means you can store your server modulescripts in ServerStorage and exploiters will never be able to see the source code, meaning they cannot steal & duplicate it, nor can they inspect server script behaviour to try and work out vulnerabilities.
While I do split all of my scripts, I do actually have a unique modulescript that is meant to be used both on server & client, which is the character health manager. This is just so I can share DamageTaken and Died callbacks to do effects on both datamodel.
In cases where you need to have the same code on client & server, you can create ‘utility’ modulescripts which share functions, or modulescripts that add methods to existing objects (I call these component modules).