I am back once again asking for more help on how to do something for my game lol. So I’m recreating the battle system from Wizard 101 and I’ve recently after someone told me put some of the stuff I thought was safe on the client on the server, but there’s still some stuff that needs to be on the client such as pressing buttons so how should I handle actions? You can either draw,pass,flee or select a card to use and so this is what I have, but I’m pretty sure an exploiter could probably mess with this?
if v.Parent.Name ~= "Cards" then
if v.Name == "Draw" then
battleFrame.Visible = false
waitingForPlayersFrame.Visible = true
action:FireServer("Draw")
--print("Draw")
--table.insert(action,"Draw")
elseif v.Name == "Flee" then
battleFrame.Visible = false
waitingForPlayersFrame.Visible = true
--print("Flee")
action:FireServer("Flee")
--table.insert(action,"Flee")
elseif v.Name == "Pass" then
battleFrame.Visible = false
waitingForPlayersFrame.Visible = true
--print("Pass")
action:FireServer("Pass")
--table.insert(action,"Flee")
end
else
local selected
selected = v.Name
battleFrame.Tip.Visible = false
battleFrame.Tip2.Visible = true
print("The Current Selected Card Is: "..selected)
while wait() do --decided to put this in a loop so that I can constantly get an updated version of the table if a new enemy or player joins
local getTable = funcFolder.getTable:InvokeServer(test1)
for _,entity in pairs(getTable.enemiesInBattle) do
for i,v in pairs(workspace.Enemies:GetChildren()) do
if v.Name == entity then
if not v:FindFirstChild("ClickDetector") then
local clickDetect = Instance.new("ClickDetector")
clickDetect.MaxActivationDistance = 500
clickDetect.Parent = v
clickDetect.MouseClick:Connect(function(playerThatPressed)
battleFrame.Visible = false
waitingForPlayersFrame.Visible = true
local target = clickDetect.Parent
action:FireServer("Cast",target,selected)
end)
end
end
end
end
end
action.OnServerEvent:Connect(function(player,action,target,selected)
print("received",player,action)
if action == "Draw" then
print(player.Name.." has decided to draw")
elseif action == "Flee" then
print(player.Name.." has decided to flee")
elseif action == "Pass" then
print(player.Name.." has decided to pass")
elseif action == "Cast" then
print(player.Name.." has casted "..selected.." on "..target.Name)
end
end)
It’s mostly fine. The only potential issue I’m spotting is if you’re trying to prevent a player from choosing a specific option by hiding the button. If the different actions can be disabled, you need to check that they’re not disabled on the server before performing the action. Even if there’s no GUI to perform an action, a hacker could fire the RemoteEvent with any arguments, so if there’s no serverside check that’d enable cheaters to perform disabled actions.
Another thing, actually. You’re assuming that target is never nil, i.e. print(... target.Name), which is going to throw an error if target is either nil or the wrong type. This can happen if the target has been destroyed while the event was being transmitted over the network, which often takes a couple 100s of ms, or if a cheater fired the RemoteEvent with arguments of the wrong type. If your game stops working because if such an error, it would enable cheaters to break and ruin the game for everyone in a server, for example if they get mad that they’re losing a game.
The best way to deal with this is to do type-checking at the top of the listener/callback/connected function. I.e.
if not (typeof(target) == "Instance" and target.ClassName == "Player") then
warn("RemoteEvent fired with invalid argument #3. Expected Player Instance, got " .. tostring(target))
return
end
You should also ensure that target is a valid target on the server, otherwise cheaters might be able to e.g. attack teammates when they aren’t supposed to, or enemies that are out of range.
Damn thanks robama again lol you’ve really helped me out on my last like 2 devforum posts.
once the player selects an option either they decided to draw, flee or cast a spell I just hide the entire battle frame which has all the buttons and stuff (so I’m not hiding a specific option) and then show the waiting for other players frame until everyone else has selected something to do because for right now I think I’m only gonna allow the player to perform one action per turn.
But basically it seems like I just need to make some checks on the server so that exploiters can’t easily break something.
p.s: I know this is not really related, but I always have a hard time knowing what exploiters can do. I know they can like mess with client stuff and remote events and like whatever, but like does this mean if I have a table in a local script can an exploiter edit that table? Because on the server (this is a card game) I generate a deck and draw 7 cards from that deck and then send the client a table for the deck and a table of the cards in hand so would this mean an exploiter could edit this? I don’t know how I’d store each deck for each player on the server which is why I just send it to the client. I assume I’d have to make like a dictionary which holds each player and then each player has a table of their deck