Which is the best way to wait for user input in a turn based multiplayer gamed based on RPCs?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By larsss31

Hi everyone,
I’m fairly new to Godot so that some of the best practices are still failing me, so I ask for forgiveness in advance :slight_smile:
I’m struggling with understanding what is the best way to wait for user input in a multiplayer setup.
Let’s say I’m developing a card game (any card game would make). “AI” logic is on the server, the clients show the hands and, when is a human player turn, should wait for his move (let’s ignore, for the sake of simplicity, timeouts for max turn duration).
Now, as RPCs are async, I cannot wait in my “AI while” for the call to return and fetch the played card this way. So the RPC from the server informs the player about which CPU card has been played and that now it’s his turn.
I tried yielding in numerous ways on the server for an RPC call from the client to trigger a signal and allow the server logic to continue, bot to no avail: the server never waits for the signal and crashes because, of course, the “card” object is empty (the user hasn’t selected the card yet)

The very problem is that this scenario must be the most frequent in any single multiplayer game (of course in turn based, but i imagine lobbies for any game, pause menus etc) and I still don’t understand which is the best way to stop processing the “AI logic” while waiting for a remote event.

I can, of course, show you a mocked up client/server snippets to better explain my setup, but I live this more like a philosophical question :smiley:

Thanks for anyone who will chip in.

:bust_in_silhouette: Reply From: larsss31

As often happens, I’ve found a viable solution a few hours after posting this question; I reply to my own comment to help others avoid the same goose chase.
In my setup, I was trying to yield for a signal directly in my while-CPU-logic loop, something in the tune of:

while turnIsRunning:
*some code*
yield(self, "user_event")
*code that uses values set before the signal is received*

And this never worked: yield returned immediately and code that relied on something set before the signal had come, crashed.
Putting the code in a function, calling the function from the while-loop and using yield in such a function, did not work either.

The solution is to yield for a function call to complete, not an object (self), and inside the called function, yield for the signal, like:

yield(getUserInput(), "completed")

and

func getUserInput():
yield(self, "user_event")

Hope this helps