Need help with OOP

My goal is to make a fireball using OOP, for security I only want to create the object inside the server and If I need it in my client then I would use :FireClient(), but I have a error saying I’m attempting to call a nil value on the local script
image

Here is my server script where I create my object and send that object to the client

local Players = game:GetService("Players")
local rs = game:GetService("ReplicatedStorage")

--Module 
local fireball = require(rs:WaitForChild("Fireball"))

--Remotes 
local REvent = rs:WaitForChild("RemoteEvent")

Players.PlayerAdded:Connect(function(player)
	local fire = fireball.new(player)
	REvent:FireAllClients(fire)
end)

This is the client side where I attempt to recieve the object from the client

local rs = game:GetService("ReplicatedStorage")

--Modules
local fireball = require(rs:WaitForChild("Fireball"))

--Remotes 
local REvent = rs:WaitForChild("RemoteEvent")

REvent.OnClientEvent:Connect(function(object)
	object:Client()
	
end)

On the local script I’m just trying to call a function that is part of the object, the function is object:Client()

The code for the constructor function and functions are here

--Services 
local Players = game:GetService("Players")
local UIS = game:GetService("UserInputService")
local rs = game:GetService("ReplicatedStorage")

--Variables 


local fireParticles = rs:WaitForChild("FireParticles")
local tool = rs:WaitForChild("Tool")

function fireball.new(Player)
	local newFireball = {}
	setmetatable(newFireball, fireball)
	
	local clone = tool:Clone()	
	clone.Parent = Player.Backpack
	clone.RequiresHandle = false 
	clone.Name = "Fireball"
	newFireball.Clone = clone
	
	local fireParticles1 = fireParticles:Clone()
	local fireParticles2 = fireParticles:Clone()
	
	newFireball.FireParticles1 = fireParticles1
	newFireball.FireParticles2 = fireParticles2
	
	return newFireball
end

function fireball:Client()
	self.Clone.Equipped:Connect(function()
		print("mybe?")
	end)
end


return fireball

The constructor function just clones a part and a tool. I then parent the tool to the players backpack. For the fireball:Client() function I’m just trying to just get it to print somthing when the tool is equipped

Why are you using OOP for such a simple thing…?
Your overcomplicated something that doesnt need to be in oop

What can I use OOP for? 30 characters

You can use it whenever you want its just a style of programming, but you need to take the time to learn it properly or you will just end up writing spaghetti code.

1 Like

You can use it for anything but like OOP was designed to organize your code and just make it much more efficient I guess, and procedural code is just as good as OOP @n_cy

EDIT : Basically I’d just use procedural code for simple stuff like things your doing, but when it comes to big systems like NPC Chat Systems, Gun Systems, Mission Systems etc, that’s where OOp can really save the day

2 Likes

I still do want know if I can create the object on the server and then send the object to the client and use functions on it on the client

If you send an object to the client they have a chance of manipulating it so I wouldnt advise doing that

Oh, metatables can’t be transferred over remotes so no, you will have to pass the properties to the client and have them instantiate the object. Alternatively, you could pass the object to client and call setmetatable with the class, note that metatable will still not be transferred just the properties of the Object.

local Class = --module class here
--Object is from the server
setmetatable(Object, Class)
4 Likes

do you think self would work? 30 char

I see a lot of think OOP is just “cool” and by using it you become like an advanced programmer. This is not true. Classes should be made when you need to instantiate objects more than once. OOP is also used for abstraction purposes. But @loveicicIe is right. I would probably make a module for a fireball attack, but making it a class is just unnecessary.

2 Likes

Yes it will work . _______________

I was going to try to use it to make something similar like a ice ball

You don’t need to only use it for multiple objects, I like to use if for single use objects as well since its adds an extra layer of abstraction and makes the code much more readable for me.

2 Likes

Creating static functions is as abstract enough. Sure, if you like make it a class. There’s just no benefit to it.

1 Like

Yeah well that’s true for all paradigms, its just a style of programming, at the end of the day it all does the same thing.

2 Likes

Yeah. I mean if your coming from languages like Java, you probably have a habit of making everything into a class. There’s really no way to help it I guess.

1 Like

There’s really no reason to steer OP away from using OOP if he feels comfortable with it - it’s not going to cause any performance issues nor effect his game in any way - it’s just a paradigm - so if he feels more comfortable with it then I see no issue with him using it.

To address a slight issue in the current solution, @cjjdawg states that metatables can’t be transferred over remotes, however seemingly contradicts himself after the comma.

It is true that metatables can’t be transferred over RemoteEvents directly, however you can jump through a few hoops to make it happen with a prefab metatable. Something like:

local tbl = {}
local tempMT = {__tostring = function() return "hello world" end}

local event = Instance.new("BindableEvent",workspace)
event.Event:Connect(function(_tbl,mt)
	setmetatable(_tbl,mt)
	print(tostring(_tbl)) -- prints "hello world"
end)

event:Fire(tbl,tempMT)

Which solves the issue, same can be done for any kind of event as well.

2 Likes

I was not contradicting myself, when you transfer it over a remote it will lose its metatable so I am adding it again on the client. It would be better in the long run not to send objects over remotes, and just serialize the object and send it to client