Having issues with object-oriented programming

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.

1 Like

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:

  1. Create a new ModuleScript for the client and the server version.
  2. 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

1 Like

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.

This is how I do it in my current project:

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).

1 Like

Thank you! this has been helpful

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.