Best method for setting up "abilities" (fastest / most protected)?

Let’s start with this, in order for a player to shoot a gun they must first click, then an event is fired to the server, the request is verified, and processed into the firing of the bullet. In order to create the best visual, usually most of the effects are first simulated on the firing client, then the server will tell the other clients about the player’s gun shot and simulate the effects on them. This avoids the issue of completely having the effect on the server which has a lot of latency for lower end devices, and issues with network ownership.

The downside: An exploiter can easily see and copy the scripts that are put onto their client. This usually isn’t much of an issue for shooter games as the firing of a weapon isn’t exactly unique code and stealing it wouldn’t really allow you to recreate the entire game.

My issue is that for my game, 90% of it is in the “abilities”, which are each unique blocks of code that do special effects like the following…

https://gyazo.com/4d60b489947fb9fb3430125d41196d4a

https://gyazo.com/6eda5ae7a40c5215c2bd9a3f63d692dd

Currently I have it so that the server will get the requests to use one of these abilities, and it will handle and create all the effects required to produce it. It let’s the Roblox server replicate to the other clients. This is usually okay for faster wifi’s and better devices, but can get very slow and laggy when there are many clients in the game. If I were to put the abilities on the client, it would in turn be much faster, but much more easy to steal and recreate.

So my questions is: Is there any way to put my scripts on the client, and protect them from being stolen? Or is there maybe another method I am not thinking about to simulate the effects on the client? Or am I stuck with this current method of client → server and letting the server handle all the effects?

Thanks!

6 Likes

You could use a mixture of hex, utf8, byte and binary to make/create code difficult to hack, and that would also protect the localscript (unfortunately not 100 percent).

[[LocalScript]]
local RE = game.ReplicatedStorage.RE --I just wrote it that way, but you can change it.
RE.FireServer("0101000069\x725c7836310111010065") --This is a mixture of hex, utf8, byte and binary text/string. It wants to say Pirate

[[Script]]
local RE = game.ReplicatedStorage.RE
RE.OnServerEvent:Connect(function(Key)
    if Key == "0101000069\x725c7836310111010065" then --if the Code is correct then …
        --Play the Abilitie or something
    end
end)

I see what you’re trying to do here, sort of encrypt a message to server. However, that isn’t the issue I am having - I’m trying to find a way to not fire an ability entirely on the server, rather fire it on each individual client without it being vulnerable to an exploiter. The server would only be used for keeping track of essential data such as distances and when an ability does damage, healing, ect…

FireAllClients() --This function can maybe help you

This is a horrible idea, don’t do this. This kind of “security” measure has been done time and time again and no longer stops anything.

2 Likes

But ServerScripts are more protected than LocalScripts, you already know that, don’t you?

Do you know the better idea, if so then please tell it here, because I also script a game and want to protect my remote events from hackers.

A good way to go about it is the often repeated “don’t trust the client” phrase. You shouldn’t be trying to “protect” your remote events, you should be designing them in a way where the server checks the validity of the actions the client is trying to do using information already available to the server. As a rule of thumb, anything the server receives through a remote events is information that can’t be trusted at all.

What you should do is often specific to your own game, however, and you should try to think as an exploiter with full access to fire your remote events in any way they want. Thinking that way is the best way to defend against it.

2 Likes

Pls can you make a exemple of this?

The best thing to do is to secure the server end of the script. Do not use variables from the client to the server when using remote events as a way to secure your server end of the script. I highly recommend you insert values into the character as a way to prevent it from being spammed/abused. For example. It may not be the best but it at least works.

remote.OnServerEvent:connect(function(player,a,b)
if player.Character:FindFirstChild(“Cooldown1”) == nil then – prevents it being fired again
local Var = Instance.new(“IntValue”,player.Character)
Var.Name = “Cooldown1”
– when this function ends, just destroy the VAR or use debris service to clear it on its own
end)

As no one really seems to understand what I am asking and the discussion has gone way off topic as to what I originally posted, I will provide an answer I got from @NovusTheory from Roblox Helpers.

You shouldn’t worry too much about protecting your game and it’s assets from the outside, rather you should let Roblox do that as that is part of their job. The main point of security should be on the game’s gameplay. Therefore you shouldn’t hold yourself back from creating scripts on the Client side if it means that your gameplay will be much smoother. You just need to make sure that your most important events are secured by the server and to not trust the client.

If someone were to steal your scripts / assets and try to reuse them for their own gain, that is what copyright laws are for.

7 Likes

For example, if you need the client to pick one of their friends from a GUI to be killed, there’s a protected (good) way of doing it and an unprotected (bad) way.

--Local Script

friendButton.Activated:Connect(function()
	chooseFriendRemoteEvent:Fire(friendButton.Name) -- Name of the client's friend gets sent to the server
end)

This would be the bad way of handling this event on the server:

chooseFriendRemoteEvent.OnServerEvent:Connect(function(client, friendName)
	for i,v in pairs(game:GetService("Players"):GetPlayers()) do
		if v.Name == friendName then
			v.Character:BreakJoints()
			break
		end
	end
end)

There is no verification that the friend name that the client sent is actually a friend of the client.
This would be the good, protected way:

chooseFriendRemoteEvent.OnServerEvent:Connect(function(client, friendName)
	local foundFriend
	
	for i,v in pairs(game:GetService("Players"):GetPlayers()) do
		if v.Name == friendName then
			foundFriend = v
			break
		end
	end
	
	if foundFriend and client:IsFriendsWith(foundFriend.UserId) then
		foundFriend.Character:BreakJoints()
	end
end)

The method above checks - on the server - if the client is actually friends with the supposed friend. It limits the client to only killing friends, instead of everyone.

2 Likes