Hi devs, I am starting a combat system from scratch and i’ve run into some issues:
Basically, my old systems always started with sending the player’s input to the server, but i’ve read some posts saying that might cause lag when different players start jitterclicking or macroing or things like that.
I obviously cannot make it rely too much on the client, so i would like to know the limits of what i can handle on the server and what on the clients:
If i were to make a skill, for example, how would i check the cooldown without constantly firing to the server at each input?
I would have normally done it with a remote function, but i guess that in fast paced combat that is not the best thing to do, is it?
What do you think of this? I would like not to put too much work on the server that is why i am so worried about this.
Check the cooldown on both the client and the server. If someone starts spamming the remote, checking on the server will allow you to kick them, while checking on the client prevents unnecessary network load.
Since the cooldown is handled on the client, the server should never receive two events separated by less than the time span of the cooldown. The only exception is network delay, so I recommend adding some leniency (for example, only kick them if they repeatedly violate the cooldown, otherwise return early).
It is not generally implemented to make server do what it doesn’t need to do.
You should make server process actual combat functions and such instead of making it process input and then from that input combat functions…
There should be cooldown implemented on server, but only for security reasons, so that exploiter cannot just send big amount of packets/different abilities at the same time and lag/have advantage.
On client, there should be input processing with desired cooldown which is the same as on server, so that non-exploiter client can’t spam server with requests, which are then rejected anyways.
For your structure, I would recommend getting simple indexes(strings or any other dataType) from player’s input, sending that index to server and server then processes ability on server with some security checks I.E cooldowns.
(Cooldown should also be on client for optimization sake as previously mentioned)
Pseudo-code:
--Client
local UserInputService = game:GetService("UserInputService")
local combatRemote = <path>
local abilityFromKeyCode = {
[Enum.KeyCode.Q] = "Parry",
[Enum.KeyCode.C] = "Dodge"
}
local function onInputBegan(inputObject, gameProcessedEvent)
if gameProcessedEvent then
return
end
local keyCode = inputObject.KeyCode
local ability = abilityFromKeyCode[keyCode]
if ability then
--Implement cooldown
combatRemote:FireServer(ability)
end
end
UserInputService["InputBegan"]:Connect(onInputBegan)
--Server
local UserInputService = game:GetService("UserInputService")
local combatRemote = <path>
local abilityIndexToFunction = {
["Parry"] = function(player, ...)
--Implement cooldown + function
end,
["Dodge"] = function(player, ...)
--Implement cooldown + function
end
}
local function onServerCombatEvent(player, abilityIndex, ...)
--Tuplets (...) could be used to recieve additional variables from player.
--Basic security
if typeof(abilityIndex) ~= "string" then
return
end
local ability = abilityIndexToFunction[abilityIndex]
if ability then
ability(player, ...)
end
end
combatRemote["OnServerEvent"]:Connect(onServerCombatEvent)