JeuWeb - Crée ton jeu par navigateur
Comment empecher l'acces multiple à une page en meme temps? - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Comment empecher l'acces multiple à une page en meme temps? (/showthread.php?tid=6012)

Pages : 1 2 3 4


Comment empecher l'acces multiple à une page en meme temps? - Argorate - 05-03-2012

Bonjour

j'ai un petit problème sur mon jeu, assez délicat à résoudre, j'expose le problème:

Un joueur m'a attaquer plusieurs fois très rapidement, et m'a tué, sauf qu'une attaque a eu lieu après ma mort (chose pas possible puisqu'on respawn ailleurs, hors de portée).
Donc cette attaque après ma mort n'aurait pas du avoir lieu.

J'ai réussi a reproduire le bug en lançant deux requêtes d'attaques très rapproché et dont la première est meurtrière, effectivement j'ai constaté que la seconde fonctionné quand même.

Je pense qu'en fait, l'initialisation de mon objet joueur dans la deuxième requête d'attaque (se faisant en début de page) s'effectue en réalité avant l'application de la méthode qui gère la mort de la première requête.

Ainsi, les deux attaques étant très rapproché dans le temps, parte dans le même état, mais n’attendent pas que les potentielles précédentes requêtes soient fini.
Contre ça, j'ai bien sur empêché, via l'interface JS, d'enchainer des attaques, mais les petits malins ouvrent deux navigateurs à la fois, et il suffit de switcher pour lancer les attaques de manière très rapproché.

Donc la solution, qui est aussi la question : comment faire pour interdire (coté serveur) à une personne d'appeler plusieurs fois la même page en même temps? (comment bloquer la page d'attaque tant qu'un attaque (émise par le joueur) est en cours?)

Voilà, j’espère que vous avez compris le problème, c'est pas évident, merci de m'aider si vous avez des idées...?


RE: Comment empecher l'acces multiple à une page en meme temps? - php_addict - 05-03-2012

n'aurais tu pas un problème avec l’ordre de résolution de tes actions?

si toutes les attaques sont empilées dans une liste (table sql par exemple) tu les prends une par une et tu résous tes attaques, et quand le joueur est mort les attaques suivantes seront à annuler (c'est un exemple)




RE: Comment empecher l'acces multiple à une page en meme temps? - Angelblade - 05-03-2012

Comme le dit php_addict Le problème c'est l'ordre de résolution des actions.
J'ai l'impression que tu essaye de résoudre ton problème avec des rustines au lieu de mettre une roue increvable.
En d'autre termes faut que tu corrige à la source sinon les ennuis vont se multiplier et le vrai problème ne seras même pas résolu.


RE: Comment empecher l'acces multiple à une page en meme temps? - Sephi-Chan - 05-03-2012

Je vois trois façons de régler le problème.


Définir un temps minimal entre deux attaques

La plus simple est de créer un cooldown sur l'action d'attaque : on ne peut attaquer que si 10 secondes (par exemple) se sont écoulées depuis l'attaque précédente.


Utiliser un verrou d'attaquer

Définir un verrou d'attaque sur tes personnages : une chaîne aléatoire stockée dans une colonne attack_lock. Pour attaquer un joueur, on envoie une requête sur la page attack/:target_id/:target_attack_lock.

Le script va chercher l'utilisateur par son ID et son attack_lock. Dès que l'attaque commence, tu régénères la valeur de la colonne attack_lock du joueur. Ainsi, lors de la seconde requête, aucun joueur ne correspondra au couple donné et l'action échouera.


Utiliser une librairie de queuing

Avec une librairie de queueing, tu empiles les demandes d'attaques et tes workers les dépilent, en vérifiant à chaque fois la possibilité d'effectuer l'action. Ici, la première fonctionnera mais pas la deuxième.

Bien sûr, ça nécessite du dédié.


RE: Comment empecher l'acces multiple à une page en meme temps? - Argorate - 05-03-2012

php_addict: je n'utilise pas de queue ni de pile, je fais du ogame-like en fait. Les actions de mon jeu sont en temps réel même si paradoxalement le jeu est un tour par tour (dans le sens où le regain de point d'action est par heure).
Donc je n'ai aucune table qui gere une pile d'action ou autres dans mon cas Wink

Sephi:
oui j'avais pensé à la solution "vérou", un champs en plus en bdd. je voulais avoir un avis exterieur Smile
Je suis pas pour le système de queue dans un tel cas, ça complique inutilement pour rien.
La solution du cooldown me parait mauvaise, puisqu'imprécise, chaque attaque ne durent pas forcement le même temps, et donc mettre un temps d'attente fixe donnerait un mauvais retour au joueur qui se sentirait bridé.

j'opte donc pour l'idée que j'avais entre vu: un champs dans la table joueur, genre: "attaque_en_cours", qui serait un boulean.

Donc aucune autre méthode possible?

genre bloqué l'ip sur une page quand une requête est déjà en cours sur cette même page, ce serait pas plus rapide/performant?


RE: Comment empecher l'acces multiple à une page en meme temps? - Sephi-Chan - 05-03-2012

Je te conseille d'opter pour ma solution plutôt que la tienne à base de booléen : elle est plus simple et plus efficace (aucune vérification à faire, on cherche juste par un couple d'information).

Les solutions à base d'IP sont inutilement complexes et inefficaces.



RE: Comment empecher l'acces multiple à une page en meme temps? - Maks - 05-03-2012

Citation :Contre ça, j'ai bien sur empêché, via l'interface JS, d'enchainer des attaques, mais les petits malins ouvrent deux navigateurs à la fois, et il suffit de switcher pour lancer les attaques de manière très rapproché.

S'ils ouvrent deux navigateurs à la fois, c'est qu'ils sont connectés sur le même compte deux fois ? Il suffit de bloquer les multi-connexions non ?

Sinon pour le cooldown, tu peux faire un cooldown qui dure le temps de l'attaque. Moi par exemple c'est le temps que mon animation se termine (pour le moment). Après ça peut être ajuster en fonction de la puissance de l'attaque comme avait proposé Sephi dans un topic que j'avais ouvert.


RE: Comment empecher l'acces multiple à une page en meme temps? - Argorate - 05-03-2012

sephi: ta solution sous entend une table juste pour ça en stockant le couple d'id_joueur lié dans l'attaque non? ou alors j'ai mal compris?
Sinon pour avec l'ip ça ne marcherais pas? on est dans le cas de requête lancé de manière très proche dans le temps, il n'y a donc aucun risque que l'ip change entre les deux, donc y a pas le problème de fiabilité sur l'ip, après pour la complexité je ne sais pas, d'où ma question ^^

marks: si je bloque comme tu l'indiques, ça bloque aussi plusieurs onglets d'ouvert sur mon jeu en même temps?
Parce que sur le principe je suis d'accord, mais si c'est handicapant car t’empêche de naviguer avec plusieurs onglet c'est un peu lourd.
Sans compter que pour mes tests de navigateurs, il m'arrive d'utiliser plusieurs navigateurs en même temps, donc ça m’embête de bloquer de cette manière pour cette raison également.
Après pour le cooldown, tu ne peux pas prévoir le temps que prend l'action d'attaque elle même, juste l'animation et encore (c'est dépendant du CPU qui l’exécute, ça peu lager). Bref je ne trouve pas ça fiable. Autant locker et délocker en début et fin de requête.


RE: Comment empecher l'acces multiple à une page en meme temps? - Sephi-Chan - 05-03-2012

Tu peux avoir un même joueur qui falsifie l'IP sur un navigateur et pas sur l'autre. Donc ton système d'IP ne marcherait pas.

Effectivement je crois bien que tu vas devoir passer par ton verrou booléen : j'oubliais que tu passais par les coordonnées du joueur lors d'une attaque (à cause de cette affaire de camouflage, notamment).


RE: Comment empecher l'acces multiple à une page en meme temps? - php_addict - 05-03-2012

désolé je ne connais pas ton jeu mais juste pour être certain (car tu parle d'Ogame):

tes actions sont du genre immédiate, où bien peuvent elles être différées? (genre "l'attaque arrivera dans 1569 secondes) ?

car si tes actions sont différées alors je vois mal comment tu peut t'en sortir sans les résoudre "dans l'ordre", soit avec un système de queue ou en les stockant dans une table SQL avec leur timestamp...

actions immédiates ou différées ?