Misunderstanding how server, module and client scripts work

I don’t understand how I can update the player’s interface

PlayerAdded (Server)

local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")

local DayController = require(ServerScriptService.DayController)

Players.PlayerAdded:Connect(function(player)
	DayController.updatePlayerDayUI(player)
end)

Constants

local Constants = {}

Constants.START_DAY_TIME = 6
Constants.START_NIGHT_TIME = 0
Constants.FULL_DAY_TIME = 24

return Constants

DayController (Module)

local DayController = {}

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Lighting = game:GetService("Lighting")

local Packet = require(ReplicatedStorage.Packet)
local Constants = require(script.Constants)

local musicTracks = {
	ReplicatedStorage.Music.DayMusic.SoundId,
	ReplicatedStorage.Music.NightMusic.SoundId
}

local currentDay = 1
local currentTrackIndex = 1

local updateDayData = Packet("UpdateDayData", {
	day = Packet.NumberU16,
	time = Packet.NumberF16
})

local music = Instance.new("Sound")
music.Parent = game.Workspace

function DayController.updatePlayerDayUI(player)
	local data = {
		day = currentDay,
		time = Lighting.ClockTime
	}
	
	print(player)

	updateDayData:FireClient(player, data)
end

local function playNextTrack()
	if currentTrackIndex > #musicTracks then
		currentTrackIndex = 1 
	end
	music.SoundId = musicTracks[currentTrackIndex]
	music:Play()
	currentTrackIndex += 1
end

function DayController.init()
	Lighting.ClockTime = Constants.START_DAY_TIME
	playNextTrack()
end

music.Ended:Connect(playNextTrack)

return DayController

UpdateDay (Client)

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Packet = require(ReplicatedStorage.Packet)

local LocalPlayer = game.Players.LocalPlayer
local Game = LocalPlayer.PlayerGui:WaitForChild("Game").GameGui
local DayFrame = Game.DayFrame

local updateDayData = Packet("UpdateDayData", {
	day = Packet.NumberU16,
	time = Packet.NumberF16
})

updateDayData.OnClientEvent:Connect(function(data)
	DayFrame.Day.Text = data.day
	DayFrame.Time.Text = data.time
end)

Init (Client)

local DayController = require(script.Parent)

DayController.init()

image

3 Likes

youre trying to init a a serversidedscript with a localscript, its worth noting that the server will never run localscripts, only module and normalscripts,

I also notice youre using Packets module, something to make it easier to use would be to treat it like normal remotes, where you store a module in replicatedstorage, then define your packets inside that module and require it both on the client and server, so it easier to modify inside that module.

1 Like

I changed the RunContext of the Init script to Server. I would like to see a solution

I have this error

ReplicatedStorage.Packet:424: attempt to index nil with ‘ResponseParameters’

Is this suphis new module? And can you show the line/lines where its erroring?

Yes, it’s a suphis module.
I wrote the packets list to the console and it is empty

Not the RunContext. The script itself is a localscript
image

1 Like

There’s 3 scripts all together

First is the Server script
image
The Server script should only be run in the following folders

  • ServerScriptService.

You can place Server Scripts in the Workspace as well but it is not recommended.

The second script is the LocalScript
image
The LocalScript should only be run in the following folders

  • ReplicatedFirst
  • ReplicatedStorage
  • StarterPlayer
  • StarterGui
  • StarterPack (This one is mostly unused)
    Same as the Server script, you can place them in Workspace but it’s also generally not recommended.

Then lastly the ModuleScripts
image
Think of them as extensions for the LocalScripts/ServerScripts. They are mainly used to breakdown code into separate files so that it’s easier to manage and debug.

Now obviously you can place these scripts anywhere in your Explorer, but generally most people follow these steps since it’s the standard.

1 Like

I would like to see a solution to my problem at least approximately.

I tried this method and it works. But I doubt that I’m doing it right. I tried to put LocalScript in ReplicatedStorage but OnClientEvent didn’t work there

Test.rbxl (75.2 KB)

Yes if you are trying to do anything player related then put it in StarterPlayer.

OnClientEvent, as the name suggests, works only on the client. So you need to put them in the folders that can use this

  • StarterPlayer
  • StarterGui
  • StarterPack (This one is mostly unused)

OnServerEvent on the other hand works only on the server.

And yes you are doing it right, although you should probably place the localscript in StarterGui since it is Gui related

1 Like

Where should I interact with the interface best, for example? In StarterPlayerScripts or in StarterCharacterScripts?

You should take a look at this video on how to manage files:

He goes fully in depth on where and how to place files and how to manage them properly.
You also must see the timestamp at the 8:39 minute mark. This part is where he shows you how he manages his files on his actual real game.

As the video suggests, you should ‘probably’ only have 1 server script and 1 local script only and require all the module scripts.


image

Notice how he only has only 1 server script and 1 local script and he is just requiring all module scripts in the folder called Modules.
(Above the local script with the red arrow)

Also, I say ‘probably’ because there are times where you need to have it’s own server/local script due to specific circumstances.
For example: using parallel lua.

Now to answer your question, you should probably create a modulescript that handles the interface and requiring it in the local script in the StarterPlayerScripts. Just like the video at the time stamped at 8:39, place your module scripts into a folder so it’s easier to access them.

I did mentioned that you should place it in StarterGui, which is also fine. Both works as they are doing the same job anyways. However, calling and requiring all the module scripts at one location only is probably better. Unless the local script you have is already fully cluttered then you can create another one.

If you have scripts that changes the player’s stats (health, speed, jump, etc…) then you can create module scripts inside of StarterCharacterScripts but not creating a local script.

Now obviously, this all just preference. But in terms of file management and efficiency, you should probably be doing this.

1 Like

Firstly, if my client scripts are stored in StarterPlayerScripts, I get an error from the Packet module
ReplicatedStorage.Modules.Packet:424: attempt to index nil with ‘ResponseParameters’

Secondly, I’m sure that I’m doing something wrong in the module scripts, I’m writing it incorrectly. It seemed easier than I thought.

Server-side

DayService

local DayService = {}

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Lighting = game:GetService("Lighting")

local Packet = require(ReplicatedStorage.Modules.Packet)
local DayConstants = require(script.DayConstants)

local musicTracks = {
	ReplicatedStorage.Music.DayMusic.SoundId,
	ReplicatedStorage.Music.NightMusic.SoundId
}

local currentDay = 1
local currentTrackIndex = 1

local updateDayData = Packet("UpdateDayData", {
	day = Packet.NumberU16,
	time = Packet.NumberF16
})

local music = Instance.new("Sound")
music.Parent = game.Workspace

local function updatePlayerDayUI(player)
	local data = {
		day = currentDay,
		time = Lighting.ClockTime
	}

	updateDayData:FireClient(player, data)
end

local function playNextTrack()
	if currentTrackIndex > #musicTracks then
		currentTrackIndex = 1 
	end
	
	music.SoundId = musicTracks[currentTrackIndex]
	music:Play()
	currentTrackIndex += 1
end

function DayService.init()
	Lighting.ClockTime = DayConstants.START_DAY_TIME
	playNextTrack()
end

game.Players.PlayerAdded:Connect(function(player)
	updatePlayerDayUI(player)
end)

music.Ended:Connect(playNextTrack)

return DayService

DayConstants

local Constants = {}

Constants.START_DAY_TIME = 6
Constants.START_NIGHT_TIME = 0
Constants.FULL_DAY_TIME = 24

return Constants

Start

local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")

local DayService = require(ServerScriptService.Server.Services.DayService)

DayService.init()

Client-side

local DayHandler = {}

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Packet = require(ReplicatedStorage.Modules.Packet)

local LocalPlayer = game.Players.LocalPlayer
local Game = LocalPlayer.PlayerGui:WaitForChild("Game").GameGui
local DayFrame = Game.DayFrame

local updateDayData = Packet("UpdateDayData", {
	day = Packet.NumberU16,
	time = Packet.NumberF16
})

updateDayData.OnClientEvent:Connect(function(data)
	DayFrame.Day.Text = data.day
	DayFrame.Time.Text = data.time
end)

function DayHandler.init()
	
end

return DayHandler

Start

local Handlers = script.Parent.Handlers
local DayHandler = require(Handlers.DayHandler)

DayHandler.init()

P.S I put the client scripts in StarterCharacterScripts and the problem was solved

I think this is the solution

Server-side

DayService

local DayService = {}

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Lighting = game:GetService("Lighting")

local DayEvents = require(ReplicatedStorage.Modules.DayEvents)
local DayConstants = require(script.DayConstants)

local musicTracks = {
	ReplicatedStorage.Music.DayMusic.SoundId,
	ReplicatedStorage.Music.NightMusic.SoundId
}

local currentDay = 1
local currentTrackIndex = 1

local music = Instance.new("Sound")
music.Parent = game.Workspace

local function updatePlayerDayUI(player)
	local data = {
		day = currentDay,
		time = Lighting.ClockTime
	}

	DayEvents.updateDayUI:FireClient(player, data)
end

local function playNextTrack()
	if currentTrackIndex > #musicTracks then
		currentTrackIndex = 1 
	end
	
	music.SoundId = musicTracks[currentTrackIndex]
	music:Play()
	currentTrackIndex += 1
end

function DayService.init()
	Lighting.ClockTime = DayConstants.START_DAY_TIME
	playNextTrack()
end

game.Players.PlayerAdded:Connect(function(player)
	updatePlayerDayUI(player)
end)

music.Ended:Connect(playNextTrack)

return DayService

DayEvents

local DayEvents = {}

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Packet = require(ReplicatedStorage.Libs.Packet)

DayEvents.updateDayUI = Packet("UpdateDayUI", {
	day = Packet.NumberU16,
	time = Packet.NumberF16
})

return DayEvents

DayHandler

local DayHandler = {}

local LocalPlayer = game.Players.LocalPlayer
local Game = LocalPlayer.PlayerGui:WaitForChild("Game").GameGui
local DayFrame = Game.DayFrame

function DayHandler.updateLocalPlayerDayUI(data)
	DayFrame.Day.Text = data.day
	DayFrame.Time.Text = data.time
end

return DayHandler

DayReceiveEvents

local DayReceiveEvents = {}

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local DayHandler = require(script.Parent)
local DayEvents = require(ReplicatedStorage.Modules.DayEvents)
local Packet = require(ReplicatedStorage.Libs.Packet)

local function updateDayUI(data)
	DayHandler.updateLocalPlayerDayUI(data)
end

function DayReceiveEvents.init()
	DayEvents.updateDayUI.OnClientEvent:Connect(updateDayUI)
end

return DayReceiveEvents

Start

local Handlers = script.Parent.Handlers
local DayReceiveEvents = require(Handlers.DayHandler.DayReceiveEvents)

DayReceiveEvents.init()