#Client -> Server -> All Clients (RPC)

1 messages · Page 1 of 1 (latest)

vocal coyote
#

Hello, this might be a dumb question but I need to clarify

In my multiplayer turn-based game, on turn change cards are drawn face down for everyone but the player in turn
The player in turn can click on cards to mark them as selected, I need to notify other players that that card has been selected

What I did was

{
  ToggleCardSelectionServerRpc(cardIndex, true)
 }

[Rpc(SendTo.Server)]
    void ToggleCardSelectionServerRpc(int index, bool selected)
    {
        ToggleCardSelectionClientRpc(index, selected);
    }

    [Rpc(SendTo.ClientsAndHost)]
    void ToggleCardSelectionClientRpc(int index, bool selected)
    {
        var card = cardsToSelectedState.Keys.ElementAtOrDefault(index);
        if (card == null)
        {
            Debug.LogError("Card not found in ToggleCardSelectionRpc");
            return;
        }

        var cardHover = card.GetComponent<CardHover>();
        cardHover.ToggleSelection(selected);
    }

so it sends to server, then server sends to all clients.

Is this common? As I've done it a lot of time and it feels more like boilerplate at this point.
or is this the usual way to do things?

I've thought about using NetworkVariables but they wouldn't be enough for everything my game needs.

Also is it wrong to just call ToggleCardSelectionClientRpc from client (non-host) side. From my understanding that would break the server-client authoritative model.

If you need more information or my words unclear please let me know.

Thanks in advance

celest bramble
#

There is no need for 2 RPCs there. SendTo.ClientsAndHost is the same as SendTo.Everyone. Personally I would use a NetworkVariable for the currently selected card.

vocal coyote
#

I'm not using SendTo.Everyone

celest bramble
#

I know. But ClientsAndHost is the equivalent of Everyone. There is no need for the server RPC

vocal coyote
#

Okay Let's say a client (not the host)
called an rpc with SendTo.Everyone

Does that break the server - client authority model?

celest bramble
#

No more than it already is. What you have currently is just rebroadcasting what the client is sending. If one player is host then sending to ClientsAndHost is literally the same as sending to Everyone

#

If you had the server/host doing some processing then rebroadcasting then you might need 2 RPCs

vocal coyote
#

Okay I understand that Everyone is the same as ClientsAndHost

#

what I'm trying to acheive is

#

Player selectes a card

#

I want to tell everyone that this player selcted this card

#

what's the correct approach using RPC

celest bramble
#

What you have is fine. Just remove the server RPC

vocal coyote
#

so just the client calling the ClientsAndHost is enough?

rapid willow
#

Using SendTo.Server makes sense if you want to make some sort of validation or other logic, before sending it further. For example, you could check if player has priority, if he's selecting a legal target, etc.

vocal coyote
#

Okay got it

#

one more question though

#

does that mean that clients are talking to each other?

#

or is it still going through the server?

#

Isn't the server supposed to be the only source of truth?

celest bramble
#

Technically no. It's still going through the server/host

vocal coyote
#

Okay

celest bramble
#

You can select specific clients to send to if you override the rpcParams, but is still goes through the server

rapid willow
#

Also, keep in mind that players may modify their client code to change its logic for their benefit (e.g., select cards they're not allowed to select). In competitive games you will want to always validate everything on the server side. In other games, it may not be necessary.

vocal coyote
#

But currently I'm trying to get this working without worrying so much about cheating

#

And maybe in the future I'll add the server validation part

#

Thanks guys

placid root
#

@vocal coyote ive been losing my mind over this exact issue all day, did you figure out the server validation part? because as far as i've found, theres no way to do so that a client cant simply just bypass by calling the server -> client rpc as if it were client -> client

vocal coyote
#

if you're going to do server validation

#

Client -> Server RPC -> Everyone RPC

placid root
#

yeah but clients can just call the everyone rpc directly, which is what ive been pulling my hair out over

#

was hoping you mightve figured something out regarding that

vocal coyote
#

well.. it's a feature

#

you might want to use it or not

#

in this case not

placid root
#

as in, a modded client could call it and bypass the server rpc

vocal coyote
#

ohh

#

so you mean the client acting as the server by calling the Everyone RPC

placid root
#

sorta

#

like in your case, a modded client could directly call ToggleCardSelectionClientRpc() and get around the server rpc

#

i feel like im going insane because they were essentially telling me that the server should never send an rpc to the client

#

because this can happen

#

but also telling me the server should do validation

vocal coyote
#

I think in RPC attribute

placid root
#

so they have my head spinning in circles wondering how a server is supposed to validate a message that it cant send

vocal coyote
#

there is require authority something

placid root
#

RequireOwnership

vocal coyote
#

let me review docs

placid root
#

yeah

#

but they told me that its checked on the local client

#

so a modded client could just remove it lol

vocal coyote
#

lol

placid root
#

the server doesnt actually do any checks

vocal coyote
#

yeah got you

#

I am sure we got something wrong

#

this can't just be lol

placid root
#

i also found this relating to this situationo

#

except, adding that would just bounce all rpc invocations regardless of who sent it since it checks if the reciever is the server, not the sender

#

however checking if params.Recieve.SenderClientId == 0 seems like its onto something

#

im just twisting myself in knots trying to understand who had the idea to expose all server -> client rpcs as client -> client rpcs as well

#

and why people are acting like its totally normal

vocal coyote
vocal coyote
#

what kind of game are you working on?

placid root
#

4 player co-op, sorta like lethal companay or phasmophobia

vocal coyote
#

oh nice

placid root
#

i just dont want somebody to go into public lobbies with a mod that lets them spawn a million particle systems by exploiting server -> client rpcs intended for vfx

#

ive been trying stuff with a little tester class

#

excuse the squiggly lines lmao i use stylecop

vocal coyote
#

mind if we hop on a call?

placid root
#

i cant atm

vocal coyote
#

that's fine

vocal coyote
placid root
#

it does seem to work as long as a client cant spoof their client id, a bit annoying that it has to be added on every server -> client rpc though

#

if a client can spoof their client id then we just gotta throw the whole library away at that point tbh

#

i dont think they can though

#

im gonna assume they cant for my own sanity lmao

drifting sierra
placid root
#

im gonna build and decompile to see how rpcparams are done under the hood

drifting sierra
placid root
#

unity doing absolutely nothing to validate that a client id isnt spoofed is bonkers to me, i do not accept that they wouldn't even implement a primitive session token system

drifting sierra
#

Either that or any call to a SendTo.Everyone Rpc will always be 0 since it's not technically client to client but client to server to client. I'm not sure how it works.

placid root
#

the sender client id gets forwarded by the server

placid root
#

do they seriously do no client id - ip mapping, or session tokens, or anything of the sort

#

what stops a client from sending SendMoneyToOtherPlayerRpc() and spoofing their client id as the richest guy in the server lmao

#

what good is server authority if it trusts what the client says

drifting sierra
placid root
#

i think you are missing the point

#

[Rpc(SendTo.Server)]
public void SendMoneyRpc(ulong recipientClientId, RpcParams rpcParams = default)

#

this runs on the server

#

or, how about this

#

we go back to your true server auth example

#

client sends inputs

#

couldn't i just spoof as another client to send the inputs?

drifting sierra
#

Yeah. Probably.

placid root
#

and you dont see the problem there?

vocal coyote
#

how are network variables secured?
server write-only

drifting sierra
#

This is where you're missing the point. Prevention of that type of stuff isn't done using a high level networking library and becomes even more of a pain to handle in a Host-Client application.

#

I'm not saying it's a non-existent issue. I'm saying you're grasping for straws thinking there's just some easy solution to just patch this issue up from the perspective of a high level library.

#

And again an issue that I would argue is not really that important to solve for an indie game, especially one that's a party game and not competitive.

placid root
#

unity touts the library as production ready for both casual and competitive games, calling it secure and robust

#

all i can think is that this cant possibly be right

vocal coyote
placid root
#

thats what im wondering as well

#

how can anything be considered secure if theres zero assurance that someone cant just spoof as someone else

#

again, im not asking for military grade security, i just want to know that someone cant inject a dll to spoof their client id when rpcs are called from 10 minutes of work

#

the server should know which connection an rpc comes from, and that connection should be associated with their client id

placid root
#

nfgo maintainers are awesome
they asked for my ideas on a solution, i implemented it, and they handled all the testing and stuff to make it happen

celest bramble
#

That is awesome. And thanks for that! Glad there was a solution that didn't blow up existing code.

drifting sierra
placid root
#

tbh that might have false positives, imagine a situation where a client calls an rpc at the same time it loses ownership (RpcInvokePermission.Owner), the server knows it isn't the owner anymore but the client doesn't yet

#

it would get kicked

#

itd be even more finnicky with distributed authority

drifting sierra
#

I'm sure there would be ways of handling that. Either way, it would primarily be helpful for server auth setups so would be dealing with RpcInvokePermission.Server anyway.

#

Not really applicable to DA anyway either