Script from tool stops working after being cloned from ReplicatedStorage to Backpack via GUI Button

Note that said script works after being cloned from a PlayerAdded event function in ServerScriptService (when player joins, clone tool to backpack).

What seems to trigger this broken script is a UI Button.

Within a LocalScript under knowformshop.ScrollingFrame.ImageButton, its intention is to Clone() the MathsBook under ReplicatedStorage to LocalPlayer.Backpack.

MathsBook.IntIncrease Script

-- VARIABLES
local LocalPlayer = script.Parent.Parent.Parent
local humanoid = LocalPlayer.Character:WaitForChild("Humanoid")
local Animator = humanoid:WaitForChild("Animator")

-- PERAMATERS

ReadAnimID = 9403285871
UnreadAnimID = 9414466097
IntIncrease = 1

local Particle = "int1"
local ParticleRepStorage = game.ReplicatedStorage.particles:FindFirstChild(Particle) 
local Sound = game.Workspace.Sound.PageFlip

-- 

local tool = script.Parent

local INT = LocalPlayer.leaderstats.Intelligence

local IntLabel = LocalPlayer.PlayerGui.mainframe.hud.IntelligenceLabel

local emitter = ParticleRepStorage:Clone()
emitter.Parent = LocalPlayer.Character:FindFirstChild("Head")


tool.Activated:Connect(function()
	print("doodoo")
	if LocalPlayer.Character.Head:FindFirstChild(Particle) then

		-- increases intelligence
		INT.Value += IntIncrease
		IntLabel.Text = INT.Value

		-- sounds

		Sound:Play()

		-- emits
		emitter:Emit(1)

		-- animates
		local ReadAnimation = Instance.new("Animation")
		ReadAnimation.AnimationId = "rbxassetid://"..ReadAnimID

		local UnreadAnimation = Instance.new("Animation")
		UnreadAnimation.AnimationId = "rbxassetid://"..UnreadAnimID

		local ReadAnimationTrack = Animator:LoadAnimation(ReadAnimation)
		ReadAnimationTrack.Priority = Enum.AnimationPriority.Action
		ReadAnimationTrack.Looped = false

		local UnreadAnimationTrack = Animator:LoadAnimation(ReadAnimation)
		UnreadAnimationTrack.Priority = Enum.AnimationPriority.Action
		UnreadAnimationTrack.Looped = false

		ReadAnimationTrack:Play()

		if ReadAnimationTrack.Stopped == true then
			UnreadAnimationTrack:Play()
		end
	end
	end)

Now to clearly point out I did not script anything like Script:Destroy() unless I did so by accident.
Any help is very much appreciated!

Cafran

The problem isn’t within the MathsBook script, but it’s about how you clone the MathBooks tool to the client. You can’t clone and reparent instances to anywhere you want through a local script. So in this case, you have to use a remote event which tells the server to clone that tool and put it under the player’s backpack.

1 Like

Even after doing research I can’t seem to wrap my head around remote events. Can you explain what you mean? Like where to put the remote events and scripts etc.

There is a server and client side in Roblox, what the server does is for everyone and other players can see this too. What the client does is not always visible for other players, and is not visible for the server too. The script simply does not exist for the server so can not be runned after being cloned by a localscript.

2 Likes

A little history lesson:

In the beginning of Roblox, both the client and server had equal say in modifying a DataModel.
The server could (and still can) do anything, change any property on anything etc.
Local scripts could essentially do the same. If a local script cloned something, changed a stat in a leaderboard etc., then it would inform the server and the server would replicate it for everyone so that a change made by one player’s computer would be seen by all players in a server.
It was kind of beautiful.

The problem with this was that it left the DataModel wide open to unintended/malicious changes - exploits.
The simplest one (which I used to do really often) was changing leaderstats in RPG places with Cheat Engine or similar products.
I could simply change the money value to 999999 and the client would actually replicate this change to the server! I could actually use this money!

There was an answer to this in particular, a kind of an anti-exploit.
Normally, in an RPG for example, you would gain EXP and money stats for killing monsters, lose money from buying weapons etc.
These are known and approved ways to change your stats.
Then, there was a script monitoring the stats.
If the stats changed because you performed one of the approved actions, then that was allowed.
If the stats changed unexpectedly, then they must’ve been changed by an exploit.
When I tried hacking my stats in one of… stravant’s games, I believe?, I got kicked and the game showed a message to EVERYONE that I had exploited! I got 0wned! What an embarrassment!

That was a very benign exploit.
Edgy kids would execute inappropriate scripts and give everyone body parts which cannot be named on the devforum.
Or just loopkill everyone. Or kick them outright. Or generate a billion Messages or GUIs to create lag.
It got really annoying for the players and caused a lot of trouble for the Roblox company because the game was supposed to be appropriate for all ages.

In 2014, Filtering Enabled was introduced.

What this meant is that the server wouldn’t simply listen to every change the client made.
If the client created a new part, cloned something, changed a part’s color… it would show up locally instantly (there is no point in stopping that), but it would not show up for anyone else.

That update also added RemoteEvents and RemoteFunctions. The client/server could Fire these to send a signal to the client/server and run code.
In effect, they allowed bypassing FilteringEnabled in ways that you want to allow in your game.

Your own LocalScript that just copies the tool to the Inventory?
It doesn’t have any effect. It would’ve done something before 2014.

An exploiter doing the same? He can’t do it either.

An exploiter exploding everyone’s heads? Other players’ characters are not his business, so the server ignores his attempt to delete parts.

In order to allow someone to explode someone else’s head, you have to create a RemoteEvent, make a script listen to it that takes another player as an argument and explodes their head, then fire that event from the client with another player as the argument.
By writing such a script, you agree that yes, exploding someone else’s head is an intended part of your game. To explode someone’s head, you must fire this event instead of just deleting the head directly.

Similarly, if there is a tool in ReplicatedStorage, just chilling, should an exploiter be able to just get it instantly without needing to do or pay anything?
No, of course not. And thanks to Filtering Enabled, he can’t.
You have to tell the server: hey, I want to pick up this book. Or buy this book.
The server then gets the signal: this player wants to buy this book. Take some of their money and clone the book into their inventory.

All other online games and online applications are Filtering Enabled!

When you submit a reply on the DevForum, you don’t just will the post into existence with Inspect Element and have it appear for everyone else. That is essentially what a local script that copies a tool into the inventory does. It’s only on your screen and no-one else sees it.
Instead, you send a network request (fire a remote event) with the arguments of: which thread to post the reply in, which post are you replying to, the body/content of the reply.
The server then receives this request and updates the thread with your new post for everyone to see.


There’s a convenient hole in FilteringEnabled, though, and that’s player-owned parts.
The player owns their own character and most unanchored parts near them.
When you move in-game, your character moves instantly and everyone else sees it happen without any RemoteEvents involved. This is because the player owns its character and is allowed to move it without FilteringEnabled stopping it.
This takes some of the load off of the server and makes physics more responsive.
It also means an exploiter can just set its Torso’s Position to teleport anywhere.

A movement anti-exploit is therefore similar to the leaderboard anti-exploit I described above: instead of approving/declining actions that come in through remotes, it has to monitor and veto changes the player makes to its character.
If the player suddenly moves 100 studs in 0.1 seconds, then it must have exploited because you can’t go that fast with 16 WalkSpeed - unless the player had just used a teleporter in the game, which is an approved way to move 100 studs in an instant.

A player that uses a teleporter (in a game with such an anticheat) should fire a remote event saying: hey, I want to use this teleporter. The server will then teleport the player without triggering the anticheat.
Even better: the player should fire a remote event saying: hey, I’m about to use this teleporter, please don’t freak out when I move 100 studs instantly, and then just do it. The server should then verify whether the player was actually close enough to the teleporter to use it and whether the player actually went to the teleporter’s destination. If not, that player must’ve done something really sussy.

My rambling ends here

6 Likes

Okay so I managed to make the remote event working last night. The problem is that the local script had parameters namely KnowformLevelReq.Value , IntelBalanceReq.Value and PurchasedTool.Value. These were Int and Object Values inside replicated storage. Since they dont influence the server I made another remote event to another script which made these parameter changes. But the problem is I want each button in the shop to fire different sets of parameter changes. Is it possible to do this without making a new script for every button that I add?

Thanks,
Cafran