Is the code below is an efficient way of handling user input via ContextActionService?
How stressful is constant remote firing (with proper handling on server)?
I’m aware that adding a strong server side check to prevent abuse is essential, but how stressful is mass client - server communication from multiple players on game performance?
I’m kinda iffy on the idea of firing a remote every userinput since I’m not super informed on how stressful on the server someone using an auto clicker would be. I’m sure adding some kind of client side check to prevent non exploiters from firing a remote every millisecond would be beneficial, but can’t exploiters still abuse this system by spam firing remotes every millisecond?
local function onInput(actionName,inputState,inputObject)
if inputState == Enum.UserInputState.Begin then
print(actionName)
if actionName == "M1" then
M1_Remote:FireServer("Combat",actionName,"OnM1Activated")
elseif actionName == "M2" then
M2_Remote:FireServer("Combat",actionName,"OnM1Activated")
elseif actionName == "Block" then
Block_Remote:FireServer("Combat",actionName,"Block")
elseif actionName == "Dash" then
Dash_Remote:FireServer("Combat",actionName,"Dash")
end
elseif inputState == Enum.UserInputState.End then
if actionName == "Block" then
Block_Remote:FireServer("Combat",actionName,"Unblock")
end
end
end
local function bindInputs()
CAS:BindAction("M1",onInput,false,
Enum.UserInputType.MouseButton1,
Enum.UserInputType.Touch,
Enum.KeyCode.ButtonR2
)
CAS:BindAction("M2",onInput,false,
Enum.KeyCode.R,
Enum.UserInputType.Touch,
Enum.KeyCode.ButtonA
)
CAS:BindAction("Block",onInput,false,
Enum.KeyCode.F,
Enum.UserInputType.Touch,
Enum.KeyCode.ButtonX
)
CAS:BindAction("Dash",onInput,false,
Enum.KeyCode.Q
)
end
bindInputs()
Don’t fire strings either
Encode data into buffers/numbers because network is a thing that actually matters the most, and it’s a field where every optimization really matters.
If you exceed 50 KB sent/recv, then your game will start to break very fast.
I have a tutorial about that if you are interested:
The problem is that strings are kind of costly for the network.
In regular numbers you can encode a lot of values for O(1) cost, but with strings it gets out of control very fast.
In regular numbers, you can have up to 52 booleans, and all of it will have the same cost.
With buffers you can have pretty much anything, but for abilities, small buffers and numbers are usually enough.
You can split a number into segments.
Etc. first 8 booleans represent 256 values (ability IDs, etc.) and others toggle ability subsets, etc., “isCrouching”,“IsSprinting”
Fascinating topic, and you can experiment with it.
I personally represent a player through 2 bytes using ProxyId and GenId
ProxyId → UserId
GenId → Versioning of ProxyId for safety
GenId prevents newly joined players from reclaiming ProxyId and being treated as the same player who left.
Yeah that makes sense. So do you handle primitive data and strings in their byte counterparts even when you’re not sending them client<-> server, or do you only encode them during client ↔ server communication and decode them once you’re done?
Also, let’s say I wanted to send a instance client ↔ server, do you also encode instances?
That depends
Usually only when sending to the server due to the fact of how Roblox implemented buffers
On the Luau side, it’s easier and cheaper to use actual tables most of the time.
Although if you write interpreter/math logic, I’m pretty sure buffers would be the way to go.