game.Players.PlayerAdded:connect(function(player)
local animation = script:FindFirstChild("Animation")
game:GetService("UserInputService").InputBegan:connect(function(inputObject, gameProcessedEvent)
if inputObject.KeyCode == Enum.KeyCode.Q and gameProcessedEvent == false then
local animationtrack = player.Character.Humanoid:LoadAnimation(animation)
animationtrack:Play()
-- rest of script...
Using user input service in server script. [SOLVED]?
1 answer
The apparent problem
Unfortunately the UserInputService and ContextActionService are all services only available to be used by the client , as it isnt replicated between server and client. Because of this, using any events, functions, and properties that are a member of either service won't work.
The Sanity Check
A common tool used by developers is what as known as a sanity check. A sanity check basically makes sure that all values sent from client to server makes sense. For example, the increase of a type of virtual currency , i.e. Gold
Say for example, I am playing a game that uses the F key to increase my gold and the creators of the game let the client calculate how much gold to get, So I modify the scripts responsible for calculating the gold increase. Since the server doesnt check if the amount of gold is logical, i can get away with giving myself any amount of gold i.e. 9e17 gold.
An example of such a script would be :
--client
local plr = game.Players.LocalPlayer
local level = plr:WaitForChild("Level")
local cas = game:GetService("ContextActionService")
local remote = game.ReplicatedStorage.RemoteEvent
function work (actions,InputState,Input)
remote:FireServer(action,level.Value * 50)
end
cas:BindAction("Work",work,false,Enum.KeyCode.F)
--server
local remote = game.ReplicatedStorage.RemoteEvent
remote.OnServerEvent:Connect(function(plr,action,money)
if action == "Work" then
local gold = plr.leaderstats.gold
gold.Value = gold.Value + money
end
end)
This is a terrible way to do something as there are no checks limiting the power of the client. Alternatively, something with a sanity check would be way better
--server
local remote = game.ReplicatedStorage.RemoteEvent
remote.OnServerEvent:Connect(function(plr,action,money)
local level = plr.Level
local gold = plr.leaderstats.gold
if action == "Work" and money == level.Value * 50 then
gold.Value = gold.Value + money
elseif money ~= level.Value * 50 then
plr:Kick("nice try")
end
end)
This would be a slightly better alternative as the server has some control over how the player can get income. However, it is not an ideal solution as of yet.
The Debounce
A debounce is a quick and easy way to make sure something doesn't happen more than you wanted it to. And in this case, can be a quick patch for any exploiter that just loops the fireserver function or anyone who uses an autoclicker (/ f presser?)
--server
local used = {}
local remote = game.ReplicatedStorage.RemoteEvent
remote.OnServerEvent:Connect(function(plr,action,money)
local level = plr.Level
if action == "Work" and money == level.Value * 50 and not used[plr] then
local gold = plr.leaderstats.gold
gold.Value = gold.Value + money
------------------------------------
used[plr] = true
delay(0.5 function()
used[plr] = nil
end)
-------------------------------------
elseif money ~= level.Value * 50
plr:Kick("nice try")
end
end)
Currently, most things are set already, However, one thing would make this a bit for efficient , that being avoiding calculating the stat increase on the client and just doing it on the server:
--client
local plr = game.Players.LocalPlayer
local level = plr:WaitForChild("Level")
local cas = game:GetService("ContextActionService")
local remote = game.ReplicatedStorage.RemoteEvent
function work (actions,InputState,Input)
remote:FireServer(action)
end
cas:BindAction("Work",work,false,Enum.KeyCode.F)
--server
local remote = game.ReplicatedStorage.RemoteEvent
local used = {}
remote.OnServerEvent:Connect(function(plr,action)
local level = plr.Level
local gold = plr.leaderstats.gold
if action == "Work" and not used[plr] then
gold.Value = gold.Value + level.Value * 50
used[plr] = true
delay(0.5 function()
used[plr] = nil
end)
end
end)
Hopefully this helped you with your task :3
4 comments
sorry for making such a long post :/
like i said, moving the entire thing to a server script just isnt possible unless you change some major areas of gameplay including not letting a InputBegan event increase stats
i also think that a remote event would be better for this purpose
Alright ima accept this because if it was not for this I would have not found a fix. As your post reminded me of something / gave me a idea on how to fix it and that idea works. Yes it still allows them to spam it. But the thing is the server script itself has a wait causing them to have to wait to use it again
This discussion is preserved as it was. New answers, comments, and votes are closed.

1 comment
well you could use sanity checks on the server :p