Page 1 of 3

[SOLVED] NotifyAllPlayersBut

Posted: 01 April 2016, 07:31
by Woodruff
Bonjour,

Je cherche à résoudre un cas d'école... J'ai un état de jeu de type 'game' dans lequel tous les joueurs piochent deux cartes. La gestion serveur marche bien avec Deck.
Par contre, quand j'envoie la notification aux joueurs, je me retrouve avec ce problème : je dois informer le joueur qui a tiré la carte (information publique verso de la carte) de quelle carte il s'agit, par contre je dois indiquer aux autres joueurs qu'il a tiré une carte de type 1 (information publique : recto de la carte).

Je fais donc (code volontairement simplifié) :

Code: Select all

NotifyAllPlayers('cardDrawn', '{player_name} draw a card of type {card_type}', array(
	'player_name' => self::getPlayerName($player_id),
	'player_id' => $player_id,
	'card_type' => $card['type'] // 1
));

NotifyPlayer($player_id, 'cardDrawnByMe', 'You draw the card {card_name} of type {card_type}', array(
	'card_name' => self::getCardInfo($card)['card_name'],
	'card_type' => $card['type'] // 1
));
Mais du coup, le joueur se trouve notifié deux fois pour la carte qu'il a tiré ! Une fois par NotifyAllPlayers qui dit qu'il a tiré une carte de type 1, et l'autre fois par son propre NotifyPlayer qui lui donne le type et le nom de la carte, c'est même tout à fait logique...

Comment faire pour ne notifier que les adversaires, càd l'équivalent de ce qui serait un NotifyAllPlayersBut($player_id, ...), afin d'éviter cette double notification ?

Ludiquement,

Tchebychev

Re: NotifyAllPlayersBut

Posted: 01 April 2016, 09:57
by pikiou
English short answer before the long french one: because of the current long pooling system used by BGA, it would be really unoptimized so it doesn't exist. You do have to use two notifications and yeah it's annoying :(

Les admins m'ont expliqué il y a deux ans que si un "NotifyAllPlayersBut" n'existait pas, c'est parce qu'il n'avait semblé nécessaire dans quasiment aucun des jeux qu'ils avaient adaptés. J'avais du creuser un peu la question pour me rendre compte qu'en réalité ça n'était hélas pas possible à cause du module externe de long pooling utilisé par BGA : les messages envoyés à un groupe d'utilisateurs nécessitent d'ouvrir un canal de discussion à ce groupe d'utilisateurs, et "NotifyAllPlayersBut" nécessiterait d'ouvrir autant de canaux que de joueurs. Hors minimiser le nombre de canaux est essentiel au bon fonctionnement du site, d'où l'absence de cette fonction.

J'ai un temps pensé coder moi-même cette fonction "NotifyAllPlayersBut" en utilisant plein de "NotifyPlayer", mais les spectateurs ne recevraient rien.
Du coup ta solution de double notification est la bonne.

Re: NotifyAllPlayersBut

Posted: 01 April 2016, 14:42
by Woodruff
Merci pour ta réponse !

English reply: so this solution implies that in notif_cardDrawn on client-side, I have to test whether it's me or not who draw the card. If it's me, nothing has to be done because the mecanism is done by notif_cardDrawnByMe, if not the interface modifies itself to show the card drawn by the opponent. However I can't avoid two messages in the log...

Hum... J'avais justement penser à boucler sur tous les autres joueurs...
Du coup, si je comprends bien, c'est dans notif_cardDrawn que je dois tester c'est moi qui pioche la carte ou pas : si c'est moi je ne fais rien (notif_cardDrawnByMe prends le relai), si c'est pas moi je modifie l'interface de manière à montrer qu'un de mes adversaires a pioché une carte...

Par contre je ne peux pas couper à deux messages dans le log... :|

Correct ?

Re: NotifyAllPlayersBut

Posted: 01 April 2016, 22:40
by Quinarbre
Yeah, you need to use silent notifications so that the player in question does not get 2 messages in the log, so it will be a mess anyway.

Here's another way to do it that I used in Colt Express for cards played down (I'm not saying it's clean ! but it does the job as expected for everyone):

Code: Select all

foreach ( $players as $player => $info )
	if ( $player != $player_id )
		  self::notifyPlayer( $player, "cardPlayed", clienttranslate( '<span class="ttl${ls}">${player_name} plays ${card_name} face down</span>' ), array(...minimal info here...) );
	else
		self::notifyPlayer( $player, "cardPlayed", clienttranslate( '<span class="ttl${ls}">${player_name} plays ${card_name} face down</span>' ), array(...extra info here...);
		
self::notifyAllPlayers( "cardPlayedSpectator", '', array(...minimal info here...) );
and in the JS

Code: Select all

setupNotifications: function()
{
	if ( this.isSpectator )
		dojo.subscribe( 'cardPlayedSpectator', this, "notif_cardPlayedSpectator" );
	...
}
		
notif_cardPlayedSpectator: function( notif )
	{
	    notif.args=this.notifqueue.playerNameFilterGame(notif.args);
	    var log = 'whatever you want';
	    dojo.place( log, $('logs'), 'first' );
	    this.notif_cardPlayed( notif );
	},
and indeed the function notif_cardPlayed discriminates whether the player is active or not in order to use the "hidden" info only if available.

C'est un peu tordu, si tu veux des explications en plus je te les donne en français :)

Re: NotifyAllPlayersBut

Posted: 02 April 2016, 14:45
by Woodruff
Thanks Quinarbre!

Your way to do seems logical, I won't discuss whether it is clean or not, as you said the important is that it's makes the job done!
I'll try to organise this your way, and if I need additional information, I'll let you know.

What's the purpose of the line:

Code: Select all

notif.args=this.notifqueue.playerNameFilterGame(notif.args);
Thank you again :)

Re: NotifyAllPlayersBut

Posted: 02 April 2016, 15:56
by Quinarbre
Tchebychev wrote:What's the purpose of the line:

Code: Select all

notif.args=this.notifqueue.playerNameFilterGame(notif.args);
It's the function that automatically detects players' names in the logs in order to color them. For usual notifications it's called automatically, but since here you're hijacking the log you need to call it explicitly otherwise the log message will appear all in black letters.

Re: NotifyAllPlayersBut

Posted: 03 April 2016, 13:53
by Rudolf
Tu filtres le message dans le notif_cardDrawn du javascript par un "if not this.isplayeractive"?
Et si c'est uen phase multiplayer, tu filtres par currentplayer?

Re: NotifyAllPlayersBut

Posted: 03 April 2016, 21:43
by Quinarbre
J'ai pas le cas avec du multiplayer je crois, et ça ne concerne pas le message de log lui-même (que tu ne peux pas intercepter) mais seulement les infos en plus (cartes à défausser/afficher/déplacer).

Mais sinon en multi tu pourrais toujours filtrer sur la présence d'un champ particulier dans notif.args.

Re: NotifyAllPlayersBut

Posted: 06 June 2020, 10:46
by fafa-fr
Hi,
I'm resurrecting an old thread to ask something to the admins, and maybe to other developers depending on the admin's answer.

Are the statements in the quote below still true today? I'd like to use a notifyAllPlayersBut( $playerId ) notif, because the active player has already received a notification for this action earlier (other players receive it only if the active player confirms it, and not if he/she cancels it). If I send a notif only to other players at the table, spectators won't receive it, and if I send a notifyAllPlayers(), even if the active player ignores the interface changes, the notification message is still written in the log (so it will be written twice for this player, since he/she has already received the same notif earlier).
pikiou wrote: 01 April 2016, 09:57 English short answer before the long french one: because of the current long pooling system used by BGA, it [a notifyAllPlayersBut() method] would be really unoptimized so it doesn't exist. You do have to use two notifications and yeah it's annoying :(

Les admins m'ont expliqué il y a deux ans que si un "NotifyAllPlayersBut" n'existait pas, c'est parce qu'il n'avait semblé nécessaire dans quasiment aucun des jeux qu'ils avaient adaptés. J'avais du creuser un peu la question pour me rendre compte qu'en réalité ça n'était hélas pas possible à cause du module externe de long pooling utilisé par BGA : les messages envoyés à un groupe d'utilisateurs nécessitent d'ouvrir un canal de discussion à ce groupe d'utilisateurs, et "NotifyAllPlayersBut" nécessiterait d'ouvrir autant de canaux que de joueurs. Hors minimiser le nombre de canaux est essentiel au bon fonctionnement du site, d'où l'absence de cette fonction.

J'ai un temps pensé coder moi-même cette fonction "NotifyAllPlayersBut" en utilisant plein de "NotifyPlayer", mais les spectateurs ne recevraient rien.
Du coup ta solution de double notification est la bonne.
If a notifyAllPlayersBut() is still impossible, is there a clean way to conditionally not display the message of a notif in the log? (in my case, if the player is active, but I could also use something in the notif args)
For now, this is what I plan to do if nothing else is possible:
EDIT: wait, actually I think this is not needed:
Separate the notif in two notifs, one with the log message only, and another one without log message, with the informations for interface changes.
Use notifyAllPlayers() for the notif with args and without message. The active player doesn't process it since the changes are already done in their interface.

END OF EDIT
The notif with the log message is sent to each non-active player with notifyPlayer( $playerId, ... ), and to spectators with a notifyAllPlayers( 'spectatorNotif', ...) that only specators subscribe to, following Quinarbre's suggestion earlier in this thread. (But I don't understand why he's manually placing the message in the log in notif_cardPlayedSpectator(), I didn't try this yet, so there might be something that doesn't work as I would expect.)

Re: [SOLVED] NotifyAllPlayersBut

Posted: 08 June 2020, 09:32
by sourisdudesert
Hi

Yes, "notifyAllPlayersBut" does not exists.

The way realtime notifications works is the following: there are 2 channels:
_ "table channel", visible by all players + spectators.
_ "player channel", visible by 1 player only.

Of course we could do something for the logs, for ex: "display log for everyone except for player X", but the cases where we need this are very limited...

In your case, you get something like:

"Player X draws a <card_type> card"
"~ You draw <card_name> ~"

I think this is pretty clear, and it does the trick.

If you want to improve this, you may want to consider to hide the previous log using javascript. However, a page refresh will make the log appear again (and it will not work in turn based).

So my advice would be: for now, let the 2 logs as they are, and let's see if this is really a problem during the Alpha testing phase.