Scripts listening to the same event getting different outputs

Now, I have two identical scripts (save for some testing prints) that are listening to the same remote event. they are both local scripts, and they are receiving a tool. However, one of the scripts is getting just the tool, none of its descendants. The other script is working just fine, getting the tool and all descendants. I tried a few different approaches but came up dry, and I give up.

Code for local scripts (one has some prints, but they make no difference as far as I can tell.):

RunService = game:GetService("RunService")
counter = 0
event = game.ReplicatedStorage.PreviewRequest
selected = false
local item

event.OnClientEvent:Connect(function(source, object)
	if item then
		item:Destroy()
	end
	if object.ClassName == "Tool" then
		local parts = object:GetChildren()
		item = Instance.new("Model")
		for i = 1, #parts do
			local part = parts[i]
			if part.ClassName ~= "Script" and part.ClassName ~= "LocalScript" then
				part.Parent = item
				if part.Name == "Handle" then
					item.PrimaryPart = part
				end
			end
		end
		object:Destroy()
	else
		item = object
	end
	item.Parent = script.Parent
	item:SetPrimaryPartCFrame(CFrame.new())
	camera = Instance.new("Camera")
	camera.Parent = script.Parent
	script.Parent.CurrentCamera = camera
	radius = 5
	center = Vector3.new()
	rad, cos, sin = math.rad, math.cos, math.sin
	selected = true
end)

while true do
	if selected == true then
		counter = counter + 1
		camera.CFrame = CFrame.new(Vector3.new(center.X + radius*cos(rad(counter%1440)), 1, center.Z + radius*sin(rad(counter%1440))), Vector3.new())
	end
	RunService["Heartbeat"]:Wait()
end

Code for server script firing the client events:

event = game.ReplicatedStorage.PreviewRequest

event.OnServerEvent:Connect(function(player, source, item, gui)
	print("Fired")
	if item == "Campfire Kit" or item == "Heater Kit" then
		item = game.ServerStorage.Entities[string.sub(item, 1, -5)]:Clone()
		item.Parent = game.ReplicatedStorage
	elseif item == "Deselect" then
		item = false
	else
		item = game.ServerStorage[item]:Clone()
		item.Parent = game.ReplicatedStorage
	end
	if item then
		item = item:Clone()
		item.Parent = gui
		print(player, source, item)
		event:FireClient(player, source, item)
	end
end)

Code for local scripts firing to the server script:

event1 = game.ReplicatedStorage.PreviewRequest
event2 = game.ReplicatedStorage.DescriptionEvent
item = string.sub(script.Parent.Name, 1, -9)
button = script.Parent
selected = script.Parent.Parent.Selected
isSelected = false

button.MouseButton1Down:Connect(function()
	print("Clicked", selected)
	local gui = script.Parent.Parent.Parent.Parent.DescriptionFrame.WorkingViewportFrame
	if isSelected == false and selected.Value == false then
		event1:FireServer(script, item, gui)
		event2:Fire(script, item, gui)
		button.Style = "RobloxRoundDefaultButton"
		isSelected = true
		selected.Value = true
	elseif isSelected == true and selected.Value == true then
		event1:FireServer(script, "Deselect", gui)
		event2:Fire(script, "Deselect", gui)
		button.Style = "RobloxRoundDropdownButton"
		isSelected = false
		selected.Value = false
	end
end)

Edit for relevant hierarchy:

You’re running object:Destroy() inside of the LocalScripts, are you sure you’re not destroying the object with one before the other has a chance to reference it? It appears to be the case.

Cause if both scripts are grabbing the object from the same remote event and one of them is running :Destroy() on the object - this is why the object has no children.

1 Like

I do not believe this is the case, since the server script should be making a new copy for each, but i’ll test it

Post Test: Nope. No difference in result.

1 Like

This is sort of confusing to look at. Which script specifically is the one that’s functioning incorrectly and what exactly is happening? I have several conclusions as to why this code is not working.

1 Like

The script on the top is what is malfunctioning.

Here is a rundown of supposed to happen:

The first script (at the bottom) is passing over a string value with the name of the desired item.
The second script (the server script in the middle) is reading that name to get the corresponding item from server storage and passing a copy to replicated for the client to use.
The last (top) script is then taking the tool, converting it to a model, and using it for a view port.

Just some constructive criticism, but I feel that you might be over complicating a few things. Try creating a function that takes in a tool object and recursively clones any BaseParts into a model.

-------------------------------------
-- Traverse the hierarchy and clone any BaseParts over to our model.
-- @param object : The object we are targeting
-- @param rModel : This is the target model that we will parent our parts to.
-------------------------------------
local function recurseForParts(object, rModel)
	if object:IsA("BasePart") then
		local c1 = object:Clone()
		c1.Anchored = true
		c1.CanCollide = false
		c1.Massless = true
		c1.Parent = rModel
	else
		for _, v in pairs(object:GetChildren()) do
			recurseForParts(v, rModel)
		end
	end
end

-------------------------------------
-- Create a model from a tool object
-- @param tool : The tool we want to use
-- @param _parent : The container we want to parent our model to.

-- @TODO : Yield while the tool is indexed. The bigger the model is, the longer it will take.
-------------------------------------
local function modelFromTool(tool, _parent)
	local returnModel = Instance.new("Model")
	returnModel.Parent = _parent

	recurseForParts(tool, returnModel)
end

-- Small example
modelFromTool(game.Workspace.Tool, game.ReplicatedStorage)

You’re also cloning objects from the ServerStorage into the ReplicatedStorage. This does not pose any additional security benefits and means that every client will see the new tool in ReplicatedStorage; you will end up with duplicates. Instead, just keep a copy of each tool in the ReplicatedStorage so players have a copy when they join the game.

Here is an example of how you better organize your client-server model. It’s not ideal, but for your situation it should do the trick.

-- On server Script

local ReplciatedStorage = game:GetService("ReplicatedStorage")

local RemoteEvent = ReplciatedStorage:WaitForChild("RemoteEvent")

local events = {
	["PrintSum"] = function(player, numx, numy)
		print("The sum of " ..numx.. " and " ..numy.." is " ..(numx + numy))
	end;
	["PrintDifference"] = function(player, numx, numy)
		print("The difference of " ..numx.. " and " ..numy.." is " ..(numx - numy))
	end;
}

RemoteEvent.OnServerEvent:Connect(function(player, tag, ...)
	local port = assert(events[tag], 'Invalid event port')(player,...)
end)



-----------------------------------------------------------------------------------------------------------------------------------------------------
-- On client LocalScript

local ReplciatedStorage = game:GetService("ReplicatedStorage")

local RemoteEvent = ReplciatedStorage:WaitForChild("RemoteEvent")

RemoteEvent:FireServer("PrintSum", 8, 2)
1 Like

They are being deleted after they have been copied, and a lot of scripts look to server storage for item copies so I am not very willing to make the switch. Either way, I will attempt to implement something along the lines of what you suggested and report back if it worked or not.

1 Like

Well, I fixed it, but it’s something I did not expect. Apparently the two scripts were negatively interacting. Disabling one fixes the other. I think cxuu was right with what he said. Either way, I will use a modified version of SuperBloxxor’s method because it’s shorter and cleaner. So, I don’t know who should get the solution check.

Edit: I guess i’ll just check myself because I don’t want this thread to be left marked as unanswered.

2 Likes