Server code not replicating to the client

Hey everyone! I’m currently having an issue where this code is not replicating to the clients, although playing on the server. Here is an explorer view:

image

Basically, I was messing around with waves from another devforum post but my only concern was that it ran on the client, therefore I was unable to make ships go up and down with the wave without lots of custom replication. Here is my server script code:

local Wave = require(script.Parent.Wave)
local Plane = script.Parent.WaterModel.Close

local Settings = {
	WaveLength = 40,
	Direction = Vector2.new(0,0),
	Steepness = .1,
	TimeModifier = 2,
	MaxDistance = 1500,
}

local TestWave = Wave.new(Plane,Settings)
TestWave:ConnectHeartbeat()

And here is the module script code:

local Wave = {}
Wave.__index = Wave

local newCFrame = CFrame.new
local IdentityCFrame = newCFrame()
local EmptyVector2 = Vector2.new()
local math_noise = math.noise
local random = math.random
local setseed = math.randomseed

local Heartbeat = game:GetService("RunService").Heartbeat
local Player = game:GetService("Players").LocalPlayer

local default = {
	WaveLength = 50,
	Gravity = 1,
	Direction = Vector2.new(0,0),
	FollowPoint = nil,
	Steepness = 0.2,
	TimeModifier = 2,
	MaxDistance = 1500,
}

local function Gerstner(Position: Vector3,Wavelength: number,Direction: Vector2,Steepness: number,Gravity: number,Time: number)
	local k = (2 * math.pi) / Wavelength
	local a = Steepness/k
	local d = Direction.Unit
	local c = math.sqrt(Gravity / k)
	local f = k * d:Dot(Vector2.new(Position.X,Position.Z)) - c * Time
	local cosF = math.cos(f)

	local dX = (d.X * (a * cosF))
	local dY = a * math.sin(f)
	local dZ = ( d.Y * (a * cosF))
	return Vector3.new(dX,dY,dZ)
end

local function CreateSettings(s: table,o: table)
	o = o or {}
	s = s or default
	local new = {
		WaveLength = s.WaveLength or o.WaveLength or default.WaveLength,
		Gravity = s.Gravity or o.Gravity or default.Gravity,
		Direction = s.Direction or o.Direction or default.Direction,
		PushPoint = s.PushPoint or o.PushPoint or default.PushPoint,
		Steepness = s.Steepness or o.Steepness or default.Steepness,
		TimeModifier = s.TimeModifier or o.TimeModifier or default.TimeModifier,
		MaxDistance = s.MaxDistance or o.MaxDistance or default.MaxDistance,
	}
	return new
end

local function GetDirection(Settings,WorldPos)
	local Direction = Settings.Direction
	local PushPoint = Settings.PushPoint

	if PushPoint then
		local PartPos = nil

		if PushPoint:IsA("Attachment") then
			PartPos = PushPoint.WorldPosition
		elseif PushPoint:IsA("BasePart") then
			PartPos = PushPoint.Position
		else
			warn("Invalid class for FollowPart, must be BasePart or Attachment")
			return
		end

		Direction = (PartPos-WorldPos).Unit
		Direction = Vector2.new(Direction.X,Direction.Z)
	end
	
	return Direction
end

function Wave.new(instance: instance, waveSettings: table | nil, bones: table | nil)
	if bones == nil then
		bones = {}
		for _,v in pairs(instance:GetDescendants()) do
			if v:IsA("Bone") then
				table.insert(bones,v)
			end
		end
	end
	
	local Time = os.time()
	
	return setmetatable({
		_instance = instance,
		_bones = bones,
		_time = 0,
		_connections = {},
		_noise = {},
		_settings = CreateSettings(waveSettings)
	},Wave)
end

function Wave:Update()
	for _,v in pairs(self._bones) do
		local WorldPos = v.WorldPosition
		local Settings = self._settings
		local Direction = Settings.Direction
		
		if Direction == EmptyVector2 then
			local Noise = self._noise[v]
			local NoiseX = Noise and self._noise[v].X
			local NoiseZ = Noise and self._noise[v].Z
			local NoiseModifier = 1
			
			if not Noise then
				self._noise[v] = {}
				NoiseX = math_noise(WorldPos.X/NoiseModifier,WorldPos.Z/NoiseModifier,1)
				NoiseZ = math_noise(WorldPos.X/NoiseModifier,WorldPos.Z/NoiseModifier,0)
				
				self._noise[v].X = NoiseX
				self._noise[v].Z = NoiseZ
			end
			
			Direction = Vector2.new(NoiseX,NoiseZ)
		else
			Direction = GetDirection(Settings,WorldPos)
		end
		
		v.Transform = newCFrame(Gerstner(WorldPos,Settings.WaveLength,Direction,Settings.Steepness,Settings.Gravity,self._time))
	end
end

function Wave:Refresh()
	for _,v in pairs(self._bones) do
		v.Transform = IdentityCFrame
	end
end

function Wave:UpdateSettings(waveSettings)
	self._settings = CreateSettings(waveSettings,self._settings)
end

function Wave:ConnectHeartbeat()
	local Connection = Heartbeat:Connect(function()
		local Settings = self._settings
		local Time = (DateTime.now().UnixTimestampMillis/1000)/Settings.TimeModifier
		self._time = Time
		self:Update()
	end)
	table.insert(self._connections,Connection)
	return Connection
end

function Wave:Destroy()
	self._instance = nil
	for _,v in pairs(self._connections) do
		pcall(function()
			v:Disconnect()
		end)
	end
	self._bones = {}
	self._settings = {}
	self = nil
end

return Wave

Server view:

Client view:

Any help would be much appreciated! Thanks.

1 Like

Why don’t you just fire a remote when a player joins to replicate it on client?

The client would be out of sync from the server

I did a test on my own bone water, I think your problem is that you request a bone table from the water which you aren’t passing causing the script to yield.

Considering that the meshpart should just have bones parented to it this should fix it:

local Wave = require(script.Parent.Wave)
local Plane = script.Parent.WaterModel.Close

local Bones = {}

local Settings = {
	WaveLength = 40,
	Direction = Vector2.new(0,0),
	Steepness = .1,
	TimeModifier = 2,
	MaxDistance = 1500,
}

for i,v in pairs(Plane:GetChildren()) do
	if v:IsA('Bone') then
		table.insert(Bones, v)
	end
end

local TestWave = Wave.new(Plane, Settings, Bones)
TestWave:ConnectHeartbeat()

print('Ran')
1 Like

That still isn’t working, I’m almost sure it is something to do with the module at this point as sending the table of bones from the server script does not work.

Make sure the modules and the script are in the right places and the water model is in workspace when doing this as it worked for me so it can’t be a module error.

Could you send me a file download as I’m extremely confused why this isn’t working, so I can compare the two.

Water.rbxl (52.0 KB)

1 Like

Sorry, WiFi went out for some time. This place also doesn’t work, I see the waves on the server but not the client again.

Client:

Server:

Maybe it is some of my studio settings? Not sure, I’ll check them. Although it doesn’t work inside of roblox either.

I’ve had go at this, it appears transform doesn’t replicate. Alternatively I managed to replicated it using tweenservice but as I said before this should be done on client as anything that’s about animating objects as it’s more resource efficient.

Water.rbxl (52.2 KB)

1 Like

Thanks for the help! As I previously mentioned, if I tried to do it on the client, it would not be synced with the server therefore the boats would not float with the waves etc… :smile: