Running a module script from the server to the client with a metatable

Hey! I’m trying to make a Objective system, and I’m trying to run a module script from the server and then run it on the client.
image
image

OnLoad() starts on the server, but I need it to also start on all clients.

How can I run the LoadObjective() from server and after that it run the OnLoad() function on clients too? , also save a metatable of objective

Im pretty new at OOP, and still trying to learn it.

Heres the scripts.

Objective Class:

local Class = {}

Class.__index = Class

local RS = game:GetService("RunService")

function Class:LoadObjective()
	if RS:IsServer() then
		self:OnLoad()
	end
	if RS:IsClient() then
		self:OnLoad()
	end
end

return Class

Objective:

local Objective = {}

Objective.__index = Objective

setmetatable(Objective, require(script.Parent))

local RS = game:GetService("RunService")

function Objective.Create()
	return setmetatable({
		ObjectiveName = script.Name
	}, Objective)
end

function Objective:OnLoad()
	if RS:IsServer() then
		print(script.Name .. " On Server")
	end
	
	if RS:IsClient() then
		print(script.Name .. " On Client")
	end
end

return Objective
1 Like

From the code you’ve sent, I can only see that you’ve required the module once. Is that on the server? Have you required the module at all on the client? Modules can’t run their own code, the code they contain is run by scripts that require it.

also please could you format that code properly it’s incredibly hard to read and find issues with…

Yeah i required it only on server, i trying to do a simple system that will be executed on server and on all clients after server-side execute. So i want to get ideas to running LoadObjective() on the client, and save the Objective metatable on client-side.
image

It’s going to need remote events to communicate what you need to load, in addition: you will need to note that metatables will not pass between the client and server if you try to do that. To pass something to the clients, create a RemoteEvent, and call :FireAllClients(info) on it and then on the clients you can receive it by RemoteEvent.OnClientEvent:Connect(function() end)

I’m not sure if that’s what you’re specifically asking for, because the wording is a bit confusing, so let me know.

The problem is i have tried to pass it, but it doesnt seem to work.
image
image

I trying to execute the LoadObjective() on client side, but it says an error

The server and client doesn’t magically share the same class. Both the server and the client run their own Luau VM, creating a cache of the required module.

When you create an objective on the server, it will not exist on the client unless you relay that info. The same applies for calling methods. This is all done through remotes.

The problem with creating a shared ModuleScript that has a different behavior based on the environment (server and client in this case) is that it gets very confusingly complex fast, especially if you are new and/or in an OOP scenario, where storing unique classes, firing remotes, and involving connections gets implemented into the mix.

Also note that functions and metatables cannot be passed through remotes, meaning you will have to (fetch and) reconstruct your server classes into client classes.

Alright, i got that, are there any ideas for initializing the client?
or will I have to create the Objective, but only on the client?

The easiest way is to keep your server class and use remotes normally to relay the info to the client.

function class:foo(...)
    remoteEvent:FireClient(player, ...)
end

I’ve actually already made a single synced OOP system from my previous post, but it gets very complicated. Here are the rough steps I took from memory:

  1. Client joins, server sets up classes with a unique id and stores them in a table. Server then relays creation to the client.
  2. Client fetches existing classes that may already exist via RemoteFunction from server and sets up a listener for new classes via RemoteEvents. The client then recreates the server class and also stores them in a table.
  3. When calling functions and methods, assure they can only be ran in the right context, and if it involves trying to call the same function/method on the other side, fire a remote to run the same function/method.

This is a very basic form of my old module. Advanced classes will implement custom signals for listener classes and events, proxies and metatables for syncing properties, etc. If you do all this, congratulations - you just reimplemented the basic concept of an Instance.

I do not recommend this route at all unless you are very skilled and knowledgeable enough to do so and if the time and effort spent is worth achieving the familiarity of what we are given now. 99.9% of the cases you wont need this, as most classes are nothing but a couple of methods and properties.

Alright, thank you very much! I’ll try to create something approximate.

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