27-04-2020, 04:24 AM
(Modification du message : 27-04-2020, 02:09 PM par L'Omniscient.)
Hello les gens,
Voilà je me lance enfin sur l'intégration des combats JCJ dans mon jeu.
Et je dois régler ce fameux problème du joueur X qui, influencé par plusieurs conditions inconnues aussi rares que de pluies d'étoiles filantes (peut-être un peu moins quand même) n'arrive pas à inscrire son attaque dans la base de données.
Voici donc les codes. Je ne copie que ceux nécessaires à la résolution du bug (puisque le joueur qui a le problème ne peut pas aller plus loin).
Le problème :
Le code fonctionne très bien SAUF avec une certaine configuration assez précise mais difficilement identifiables :
- Il ne touche que certain joueurs, TOUJOURS les mêmes.
- Il n'affecte ces joueurs QUE contre certain joueurs, et TOUJOURS les mêmes opposants
- Il pose problème QUE lorsque le joueur touché attaque en deuxième.
Dans ces conditions, le joueur qui a des soucis n'arrive pas à inscrire son attaque dans la table. Le joueur qui n'arrive pas à inscrire son attaque finit par entrer dans la condition qui le "reload". Donc j'ai l'impression qu'il est bloqué jusqu'à ce que l'autre joueur ait finit sa boucle a lui.
De ce fait, et après une petite analyse, j'ai pu remarquer que les joueurs touchés étaient généralement ceux avec de mauvaises connexions internet.
Et ça se produit contre ceux qui semblent avoir d'excellentes connexions.
Je me suis posé la question suivante : est-ce dû à la différence de connexion ?
Du coup le joueur 2 n'arrive pas à UPDATE son attaque. L'éciture de la table serait-elle lock par le joueur à connexion trop rapide qui la lit en boucle ?
C'est hyper énigmatique cette histoire. J'ai essayé de regarder ce qu'il se passait dans ma table durant la lecture en boucle, et la case "?" du deuxième joueur ne s'UPDATE pas sauf quand le joueur 1 l'UPDATE au bout de 30 secondes, ensuite seulement le deuxième joueur peut poursuivre son chemin, trouver le "Yes" et dire au client qu'il a été déco (ce qui est faux du coup :x). On dirait qu'il est bloqué à un endroit et ne peut poursuivre son chemin que lorsque le premier joueur a fini le sien.
Le PHP finit par revenir vers le client, donc pas d'erreur dans le code PHP.
C'est hyper compliqué à débuguer Ma solution serait d'écrire la boucle côté JS et pas côté Serveur, en espérant que le joueur quitte bien la table pour laisser l'autre y entrer comme il veut.
Quel est votre avis sur cette histoire ? Demain je refais les tests pour voir si c'est bien le PHP qui renvoie son info au client ou si c'est le JS qui force la récupération de l'info au bout d'un certain temps. (Heureusement que j'ai un ami avec qui ce bugue se produit sur moi, je sais pas comment je ferais sinon XD)
EDIT :
En reregardant un peu ce que vous m'aviez dit, ma table est en MyISAM, apparemment ça pourrait lock la BdD.
Prochains tests à faire :
- passer ma table en InnoDB
- essayer de commit la table d'update du joueur 1
EDIT 2:
Je viens de me rendre compte Xenos, que quand tu m'avais dis de commit la table, j'ai commit la table de lecture, et pas celle d'UPDATE ! Peut-être que je dois commit la table d'update ?
Voilà je me lance enfin sur l'intégration des combats JCJ dans mon jeu.
Et je dois régler ce fameux problème du joueur X qui, influencé par plusieurs conditions inconnues aussi rares que de pluies d'étoiles filantes (peut-être un peu moins quand même) n'arrive pas à inscrire son attaque dans la base de données.
Voici donc les codes. Je ne copie que ceux nécessaires à la résolution du bug (puisque le joueur qui a le problème ne peut pas aller plus loin).
function search_attaque() {
global $bdd;
global $qui;
$bdd->beginTransaction();
if ($qui['IDCombattantActif'] == $_SESSION['ID']) {
$attaque=$bdd->query('SELECT AttaquePassif FROM z_erentis_combats_jcj WHERE IDCombattantActif = "'.$_SESSION['ID'].'" ');
} else if ($qui['IDCombattantPassif'] == $_SESSION['ID']) {
$attaque=$bdd->query('SELECT AttaqueActif FROM z_erentis_combats_jcj WHERE IDCombattantPassif = "'.$_SESSION['ID'].'" ');
}
$bdd->commit();
$attaque = $attaque->fetch();
return $attaque[0];
}
/* Trop tard pour l'attaque de l'adversaire */
function cherche_et_toolate() {
global $bdd;
global $qui;
$time = 0;
$attaque = search_attaque();
/* On cherche l'attaque du joueur adverse jusqu'à ce qu'on la trouve */
while ($attaque == "?" AND $time < 30) {
$attaque = search_attaque();
if ($attaque == "?") {
sleep(2);
}
$time = $time + 2;
}
if ($time >= 30) {
$attaque = "X";
if ($qui['IDCombattantActif'] == $_SESSION['ID']) {
$use = $bdd->prepare('UPDATE z_erentis_combats_jcj SET AttaquePassif = "X", AttaqueActif = "?", TooLatePassif = "Yes", Tour = Tour + 0.5 WHERE IDCombattantActif = ?');
} else if ($qui['IDCombattantPassif'] == $_SESSION['ID']) {
$use = $bdd->prepare('UPDATE z_erentis_combats_jcj SET AttaqueActif = "X", AttaquePassif = "?", TooLateActif = "Yes", Tour = Tour + 0.5 WHERE IDCombattantPassif = ?');
}
$use->execute(array($_SESSION['ID']));
$aten['Nom'] = "X";
}
return $attaque;
}
if ($_POST['passe'] == "yes") {
/* RECUPERATION DES DONNEES DE L'ATTAQUE DU JOUEUR */
$recup_attaque = $bdd->prepare('SELECT * FROM z_erentis_attaques WHERE Element LIKE ? AND Hand = ? AND Moove = ?');
$recup_attaque->execute(array("%".$_POST['element']."%", $_POST['nhand'], $_POST['nmoove']));
$at = $recup_attaque->fetch();
/* Si l'attaque n'existe pas on la nomme X */
if (empty($at['Nom'])) {
$at['Nom'] = "X";
$at['ID'] = "X";
} else {
$vitesse_jo = $at['Vitesse'];
}
} else {
$at['ID'] = "0";
$at['Nom'] = "Concentration";
}
/* On insère l'attaque du joueur et on augmente le tour */
if ($qui['IDCombattantActif'] == $ID) {
$cherche_attaque = $bdd->prepare('SELECT AttaqueActif, TooLateActif FROM z_erentis_combats_jcj WHERE IDCombattantActif = ?');
$cherche_attaque->execute(array($ID));
$attaque_avant_choix = $cherche_attaque->fetch();
if ($attaque_avant_choix[0] == "?") {
$use = $bdd->prepare('UPDATE z_erentis_combats_jcj SET AttaqueActif = ?, TooLateActif = "No", Tour = Tour + 0.5 WHERE IDCombattantActif = ?');
$use->execute(array($at['ID'], $ID));
}
} else if ($qui['IDCombattantPassif'] == $ID) {
$cherche_attaque = $bdd->prepare('SELECT AttaquePassif, TooLatePassif FROM z_erentis_combats_jcj WHERE IDCombattantPassif = ?');
$cherche_attaque->execute(array($ID));
$attaque_avant_choix = $cherche_attaque->fetch();
if ($attaque_avant_choix[0] == "?") {
$use = $bdd->prepare('UPDATE z_erentis_combats_jcj SET AttaquePassif = ?, TooLatePassif = "No", Tour = Tour + 0.5 WHERE IDCombattantPassif = ?');
$use->execute(array($at['ID'], $ID));
}
}
if (isset($attaque_avant_choix[1]) AND $attaque_avant_choix[1] == "Yes") {
$attaque_lancee_jo = "reload";
if ($qui['IDCombattantActif'] == $_SESSION['ID']) {
$use = $bdd->prepare('UPDATE z_erentis_combats_jcj SET AttaqueActif = "?", TooLateActif = "No" WHERE IDCombattantActif = ?');
} else if ($qui['IDCombattantPassif'] == $_SESSION['ID']) {
$use = $bdd->prepare('UPDATE z_erentis_combats_jcj SET AttaquePassif = "?", TooLatePassif = "No" WHERE IDCombattantPassif = ?');
}
$use->execute(array($_SESSION['ID']));
} else {
$attaque = cherche_et_toolate();
/* Suite du code */
}
Le problème :
Le code fonctionne très bien SAUF avec une certaine configuration assez précise mais difficilement identifiables :
- Il ne touche que certain joueurs, TOUJOURS les mêmes.
- Il n'affecte ces joueurs QUE contre certain joueurs, et TOUJOURS les mêmes opposants
- Il pose problème QUE lorsque le joueur touché attaque en deuxième.
Dans ces conditions, le joueur qui a des soucis n'arrive pas à inscrire son attaque dans la table. Le joueur qui n'arrive pas à inscrire son attaque finit par entrer dans la condition qui le "reload". Donc j'ai l'impression qu'il est bloqué jusqu'à ce que l'autre joueur ait finit sa boucle a lui.
De ce fait, et après une petite analyse, j'ai pu remarquer que les joueurs touchés étaient généralement ceux avec de mauvaises connexions internet.
Et ça se produit contre ceux qui semblent avoir d'excellentes connexions.
Je me suis posé la question suivante : est-ce dû à la différence de connexion ?
Du coup le joueur 2 n'arrive pas à UPDATE son attaque. L'éciture de la table serait-elle lock par le joueur à connexion trop rapide qui la lit en boucle ?
C'est hyper énigmatique cette histoire. J'ai essayé de regarder ce qu'il se passait dans ma table durant la lecture en boucle, et la case "?" du deuxième joueur ne s'UPDATE pas sauf quand le joueur 1 l'UPDATE au bout de 30 secondes, ensuite seulement le deuxième joueur peut poursuivre son chemin, trouver le "Yes" et dire au client qu'il a été déco (ce qui est faux du coup :x). On dirait qu'il est bloqué à un endroit et ne peut poursuivre son chemin que lorsque le premier joueur a fini le sien.
Le PHP finit par revenir vers le client, donc pas d'erreur dans le code PHP.
C'est hyper compliqué à débuguer Ma solution serait d'écrire la boucle côté JS et pas côté Serveur, en espérant que le joueur quitte bien la table pour laisser l'autre y entrer comme il veut.
Quel est votre avis sur cette histoire ? Demain je refais les tests pour voir si c'est bien le PHP qui renvoie son info au client ou si c'est le JS qui force la récupération de l'info au bout d'un certain temps. (Heureusement que j'ai un ami avec qui ce bugue se produit sur moi, je sais pas comment je ferais sinon XD)
EDIT :
En reregardant un peu ce que vous m'aviez dit, ma table est en MyISAM, apparemment ça pourrait lock la BdD.
Prochains tests à faire :
- passer ma table en InnoDB
- essayer de commit la table d'update du joueur 1
EDIT 2:
Je viens de me rendre compte Xenos, que quand tu m'avais dis de commit la table, j'ai commit la table de lecture, et pas celle d'UPDATE ! Peut-être que je dois commit la table d'update ?