Désyncronisation Mémoire sur serveur intégrer.



  • Aimez vous les bug qui échappe à toute logique ? Alors vous allez être servie…

    Tous d’abord, voici 3 log assez technique :



    chaque élément est représenté de la façon suivante : @pointeurMémoire-id:nom(estActif).

    Maintenant passons à la description du fonctionnement :

    Chaque Elément est supposé être unique. On utilise les fonction addOrGet(String name) et findById(int id) pour obtenir nos instance.

    On initialise les éléments coté serveur grâce à VanillaInitialization
    qui est appeler sur CommonElementalConstante sur la fonction onServerStart(MinecraftServer server)

    Coté client, on les initialises sur DataEvent dans la fonction onClientConnectToServer(ServerConnectionFromClientEvent event).

    Quelque soit la méthode utilisé, un élément est ajouté dans une variable LIST_OF_ELEMENT qui est de type map, ce qui n'autorise qu'une seul instance par clé (la clé étant le nom)

    Ceci initialise donc nos éléments. La liste des éléments est ensuite appeler dans plusieurs fonction. Celle qui nous intéresse est celle de la fonction completeArray(float defaultValue) dans ElementalMatrix. Cette dernier remplis un autre map qui assosie Element (clé) et Float (valeur). Elle assure que nos matrice soit correctement remplis avec tout les éléments existant. Elle est systématiquement appeler à la création d'une matrice.

    Sur les log précédent, en serveur intégrer, pour une raison échappant à toute logique, la matrice de défense n'utilise pas la même liste que celle en attaque.

    Tournons nous donc vers la méthode de création :
    MonsterStats et PlayerStats sont assez similaire.
    Le premier constructeur (coté client) n'initialise rien (le second coté serveur initialise notre objet via la classe AbstractStats en lisant le fichier json)
    joueurs et entité sont séparer a cause d'un problème que j'avais récemment abordé sur la non synchronisation des id d'entité player, néanmoins le fonctionnement reste strictement similaire.

    La class MonsterStatsPacket est reçu coté client et permet d'initialisé le monstre. Une liste MONSTER_STATS, disponible sur Variable, puis initialisé sur CommonElementalConstante permet d'obtenir la liste de toute les class à implémenter au monstre. On créer donc une nouvelle instance grâce à clazz.newInstance();, puis on utilise la fonction fromByte(buf); disponible dans chaque objet.

    Dans le cas d'un monstre, on implémente deux matrice (AttackMatrix et DefenceMatrix) qui sont très similaire.
    La fonction fromByte de toute à l'heure est disponible sur la classe mère ElementalMatrix.

    La fonction est donc strictement similaire entre les deux objet.
    Revenons à la fonction. Elle utilise la fonction Element.findById(key). key étant un entier reçu. Revenons donc à notre class Element. La fonction vas regardé si il existe une correspondance sur la variable REF_INT_STRING. cette dernier est initialisé au même moment que notre liste d'élément. elle permet en faite d'associer l'id et le string en dehors des objets pour une recherche simplifié (et accéléré).

    Voila le fonctionnement.

    Pour finir, parlons du problème :

    Sur serveur intégré uniquement, la matrice de défense uniquement (et toujours elles), est initialisé grâce a des instances d'éléments fantôme… Ces éléments ne sont pas référencé, il n'existe pas (ou ne sont pas accessible), mais pourtant... Il sont la...
    C'est assez gênant...

    Oui, je pourrait bêtement corrigé le problème en remplaçant la clé Element par String dans mes matrice mais cela me gène : j'ai des variables fantôme qui sont créer sans raison apparente... De plus, rien ne me prouve que ces éléments soit correctement initialisé (l'affichage ne montre que la base)...



  • Je n'ai rien compris : quel est le but ? A quoi ça sert ?



  • Pour expliqué le but, il aurai fallut que je présente une bonne partie du mod ^^'
    En outre, j'ai finalement résolu le problème après une illumination (merci les vieux sujet du fofo x) )

    Pour simplifier, disons que nous avons des matrices pour calculer les dégâts.
    Ces matrice sont régis par une règle simple de Clé/Valeur.
    Ces clés sont des instances d'Element, une class custom.
    Chaque instance de cette class est supposé unique, pourtant, je me retrouvais avec des instances fantôme.
    Sur les log, les pointeurs mémoire de ma matrice de défense pointé sur des éléments inconnus, mais uniquement sur serveur intégrer.
    Pourtant, ces éléments étaient des copies parfaites (ou tous du moins sur les données de base) de mes éléments.
    En résulte alors qu'aucune fonction des matrices ne donnaient de résultat : comme les clés ne correspondaient pas, il renvoyais à chaque fois null (Java vérifiant que le pointeur en mémoire soit le même pour considérer un objet comme identique, même si les objets sont des copies conformes).

    En faite, mon problème venais d'un coup du sort, mêler a une erreur de compréhension.
    Le serveur intégré ne duplique pas les variables que j'ai pus créer. C'est une erreur sur la compréhension du principe de Serveur intégrer : il ne lance pas une seconde instance privé comme je le pensais, il lance uniquement quelque routine permettant de faire fonctionné le serveur intégrer. Cette petite différence entraîne un changement énorme : les variables sont partagés, il faut donc pensé au fait qu'elle peuvent déjà existé si la fonction a déjà été appeler ServerSide.

    Hors, mes éléments sont généré ServerSide durant le lancement du serveur. Lorsque le client rejoignais le jeu, il recevais chaque éléments pour initialisé sa propre instance. sur serveur intégré, ma propre instance était déjà initialisé.. (note : sur serveur externe, cette manip est obligatoire)
    Ma méthode actuel écrasais les éléments existant, je n'aurai donc pas du avoir de problème (si ce n'est que j'effectuais une action inutile supplémentaire sur serveur intégré)

    Mais voila, coup du sort : Entre le temps ou le serveur intégrer démarre, et le temps ou l'event PlayerJoin est déclenché, il se passe un court lapse de temps. Courts lapse durant lequel certaine entité on pus être initialisé (le Spawn du monde). Manque de bol (ou coup de bol) j'effectuai mes teste sur une entité qui était chargé avant*. Elle utilisais donc les éléments créer au lancement du serveur (éléments qui étais ensuite supprimé lorsque le client arrivais)

    Toute les entité situé au Spawn étais donc initialisé avec des vielles instances qui n'étais plus accessible une fois le joueurs connecté.
    Pour évité le bug, j'ai donc ajouté une vérification sur la création, si l'instance existe déjà, il l'ignore.

    • raison pour laquelle je n'ai pas eu ce bug immédiatement après avoir rajouté cette fonctionnalité, et pourquoi il n'avais pas toujours lieu)


  • De toute façon tu n'es pas censé accéder aux variables directement dans la mémoire



  • J'ai jamais dis que j'accéder directement au variable via des pointeurs…
    Le bug que j'avais étais du au fait que je n'avais pas la même instance de ma variable. L'affichage des pointeurs permet juste de mettre en évidence ce problème (les toString renvoyant exactement la même chaîne, mais les adresse mémoire sont différente : c'est un objet différent).

    Le fonctionnement du Java est tel que la fonction == (si elle n'as pas été redéfinis comme pour les primitives) renvoie true si, et uniquement si les pointeurs mémoire sont identique.
    Si tu clone un objet, et tu vérifie qu'il soit == a l'original, java retourne faux.

    Apparemment, la vérification des clé sur "HashMap" se fait via == ( ou obj1.equal(obj2))



  • Effectivement, c'est le principale de la POO. Je vois toujours pas l'utilité de regarder l'adresse en mémoire



  • (les toString renvoyant exactement la même chaîne, mais les adresse mémoire sont différente : c'est un objet différent).

    Sur les log, j'avais EXACTEMENT la même chose, mais pourtant toute les fonction retournais 0. Mon objet étais une copie parfaite. Seul l'affichage de l'adresse mémoire m'as permis de mettre à jour le fait que ce soit une autre instance.

    Si un exemple est plus parlant, j'avais ca :

    
    [Server]-[WARNING] Element : 0:normal(true) is not references in Matrix : {6:thunder(true)=1.0, 2:water(true)=1.0, 8:dark(true)=-1.0, 4:dirt(true)=1.0, 0:normal(true)=1.0, 10:hunger(true)=0.0, 7:holy(true)=1.5, 1:fire(true)=1.0, 3:wind(true)=1.0, 5:wood(true)=1.0, 9:poison(true)=1.0}