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