Javascript WriteVarInt non fonctionnel

Inscrit
15 Avril 2020
Messages
6
Reactions
1
#1
Bonjour à tous,

Cela fait une semaine que j'ai commencé la création d'un bot socket pour D2 en javascript, j'ai trouvé sur ce forum pleins d'informations qui me sont très utile et qui m'ont permis d'avancer à grand pas (au début du moins).

J'ai donc réussit à créer une connexion socket, à écrire mes reader/writer, à désérialiser les paquet 1 et 3, puis je me suis penché sur le 4 qui m'a donné du fil à retordre pendant plusieurs jours. J'ai lu tous les sujets qui en parlaient, puis j'ai compris que ce n'était pas la source du problème. J'ai donc fait des tests sur les paquets que j'avais déjà reçu pour voir si j'arrivais à les sérialiser sans problème (le 1 et 3) puis à les désérialiser avec le tool en ligne qu'a mis à disposition Labot (merci à toi). Et en effet, la prophétie a (encore) frappé, mon problème vient en faite de mon writer. Plus précisément de la méthode WriteVarInt que je comprends à vrai dire, pas vraiment.

Après encore quelques jours de recherches, en lisant ce qu'il se dit dans plusieurs sujets, j'ai toujours une erreur quelque part. Voici la traduction de base que j'en ai faite (une traduction des sources du jeu):
Code:
  writeVarInt (value) {
    var b = 0;
    var ba = new ByteArray();
    if (value >= 0 && value <= CustomDataWrapper.MASK_01111111) {
      ba.writeByte(value);
      this.writeBytes(ba);
      return;
    }
    var c = value;
    var buffer = new ByteArray();
    while (c !== 0) {
      buffer.writeByte(c & CustomDataWrapper.MASK_01111111); // à partir de là ça part en cacahuète pour mon cerveau
      buffer.position = buffer.length - 1;
      b = parseInt(buffer.readByte());
      c = c >>> CustomDataWrapper.CHUNCK_BIT_SIZE;
      if (c > 0) {
        b = b | CustomDataWrapper.MASK_10000000;
      }
      ba.writeByte(b);
    }
    this.writeBytes(ba);
  }
Mon problème vient de la ligne 19, quand j’essaie de sérialiser le paquet 3 que j'ai reçu, la méthode writeByte me renvoi cette erreur :
Code:
RangeError [ERR_OUT_OF_RANGE]: The value of "value" is out of range. It must be >= -128 and <= 127. Received 177
Voici le code :
Code:
  writeByte(value) {
    this.expand(1);
    this.buffer.writeInt8(value, this.position++);
  }

  expand(value) {
    if (this.bytesAvailable < value) {
      const old = this.buffer;
      const size = old.length + (value - this.bytesAvailable);
      this.buffer = Buffer.alloc(size);
      old.copy(this.buffer);
    }
  }
Si vous avez une idée pour me mettre sur la bonne voie, ce serait super, parce qu'à force de chercher je commence à voir complétement floue.
Merci pour votre aide !
 
Dernière édition:
Inscrit
15 Avril 2020
Messages
6
Reactions
1
#3
J'étais tombé dessus en parcourant le forum, je l'avais essayé mais j'obtiens toujours la même erreur ... Quelque chose doit m'échapper, mais je ne comprends pas quoi.
Voila la traduction que j'en ai faite, et qui me renvoi la même erreur:
Code:
  writeVarInt (int) {
    var local_5 = 0;
    var local_2 = new CustomDataWrapper();
    if (int >= 0 && int <= CustomDataWrapper.MASK_0) {
      local_2.writeByte(int);
      this.writeBytes(local_2.buffer);
      return;
    }
    var local_3 = int;
    var local_4 = new CustomDataWrapper();
    while (local_3 !== 0) {
      local_4.writeByte((local_3 & CustomDataWrapper.MASK_01111111));
      local_4.position = local_4.length - 1;
      var local_4_reader = new CustomDataWrapper(local_4.buffer);
      local_5 = local_4_reader.readByte();
      local_4 = new CustomDataWrapper(local_4_reader.buffer);
      local_3 = (local_3 >> CustomDataWrapper.CHUNCK_BIT_SIZE);
      if (local_3 > 0) {
        local_5 = local_5 | CustomDataWrapper.MASK_10000000;
      }
      local_2.writeByte(local_5);
    }
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#4
A mon avis ça vient du local_3 ligne 17, qui ne prend pas la bonne valeur.

A l'époque, j'avais mis plusieurs conversions et ce n'est surement pas par hasard.

local_3 = (int)((uint)local_3 >> CHUNCK_BIT_SIZE);

Tu devrais vérifier les valeurs avec un point d'arrêt, à ce niveau.
 
Inscrit
15 Avril 2020
Messages
6
Reactions
1
#5
J'ai bien analysé toute la méthode, j'ai aussi posé les opérations manuellement, pour essayer de comprendre le fonctionnement, voici ce qu'il en ressort:
Code:
  writeVarInt (value) {
    var b = 0;
    var ba = new CustomDataWrapper();
    if (value >= 0 && value <= CustomDataWrapper.MASK_01111111) {
      ba.writeByte(value);
      this.writeBytes(ba);
      return;
    }
    var c = value; // c = 305
    var buffer = new CustomDataWrapper();
    while (c !== 0) {
      buffer.writeByte(c & CustomDataWrapper.MASK_01111111);
      /**
       * Pour chaque bit 1=1, on renvoie 1 sinon 0 puis on convertit en décimal
       * 305 & 127 = 100110001 & 001111111 = 000110001 = 49
       */
      buffer.position = buffer.length - 1;
      b = parseInt(buffer.readByte()); // b = 49
      c = c >>> CustomDataWrapper.CHUNCK_BIT_SIZE;
      /**
       * On décale de 7 bits sur la droite en ajoutant des 0 sur la gauche et en enlevant ceux de droite
       * 305 >>> 7 = 100110001 >>> 7 = 000000010 = 2
       *
       * Et si je mets l'opérateur >> on décale de 7 bits sur la droite en enlevant ceux de droite
       * 305 >> 7  = 100110001 >> 7  = 10 = 2
       * Si le nombre est positif, ça revient toujours au même ici non?
       */

      if (c > 0) {
        b = b | CustomDataWrapper.MASK_10000000;
        /**
         * Pour chaque bit qui vaut 1, on renvoie 1 puis on convertit en décimal
         * 49 | 128 = 00110001 | 10000000 = 10110001 = 177
         */
      }
      ba.writeByte(b);
    }
    this.writeBytes(ba);
  }
Sinon à la ligne 36 en utilisant la méthode unsigned j'esquive la limitation de taille, et ça marche pour le paquet que je test en ce moment parce qu'il ne fait "que" 177, mais cela pourrait me causer des problèmes plus tard, non?
 
Dernière édition:

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#6
Je maintiens ma théorie,

Tu as essayé de convertir ta variable C en uint, de faire le décalage de 7 bits puis de la reconvertir en int ?

Peut-être que je me trompe mais je suis persuadé que ça vient de la ligne en question.

Sinon, oui, ça te posera forcément des problèmes futurs.
 
Inscrit
28 Juin 2013
Messages
37
Reactions
29
#7
Salut!
Si tu n'es pas allergique au C++, j'ai mis en ligne une implémentation ici. La documentation de la fonction permet d'expliquer un peu la partie que tu dis ne pas comprendre.

Quelques remarques sur ton code (je n'ai jamais touché au JS, peut-être que mes remarques seront à côté de la plaque, dans ce cas excuse moi par avance):
  1. Le code
    Code:
    buffer.writeByte(c & CustomDataWrapper.MASK_01111111);      
    /**
     * Pour chaque bit 1=1, on renvoie 1 sinon 0 puis on convertit en décimal
     * 305 & 127 = 100110001 & 001111111 = 000110001 = 49
     */
     buffer.position = buffer.length - 1;
     b = parseInt(buffer.readByte()); // b = 49
    pourrait être simplifié en juste b = c & CustomDataWrapper.MASK_01111111 non?
  2. Ton premier if qui traite le cas "particulier" quand la valeur à encoder peut être représentée sur 7 bits n'est pas utile. Si tu l'enlève, la boucle while marchera comme prévu, même pour ce cas "particulier" (qui n'est pas vraiment particulier en fait).
 
Inscrit
15 Avril 2020
Messages
6
Reactions
1
#8
Salut
Je vais tester ça BlueDream, je reviendrais ici te dire ce qu'il en est.

Nelimee, je ne me m'y connais pas beaucoup en C++, mais ta docu m'a très bien expliqué le principe de fonctionnement des WriteVar.
Dans un byte, si le 1er bit est à 0 c'est que la valeur est entièrement écrite dans les 7 autres bits, et s'il est à 1, c'est que le prochain byte sera la suite de cette valeur (hormis le 1er bit du coup, qui lui aussi dira s'il y a une suite).
Pour ce qui est de mon code, celui-ci n'est qu'un simple c/c du DofusInvoker traduit en JS, pour le moment je ne cherche pas encore à optimiser ce code, mais simplement à comprendre son fonctionnement et à arriver à quelque chose de fonctionnel. Travailler sur des buffers est nouveau pour moi, je ne suis qu'en période d'apprentissage :D

Merci à vous deux pour votre aide, c'est très appréciable !
 
Dernière édition:
Inscrit
3 Mai 2020
Messages
40
Reactions
14
#9
Salut !

Voici ma version JS du writeVarInt :

Code:
writeVarInt(param1) {
        var _loc5_ = 0
        var _loc2_ = new ByteArray()
        if (param1 >= 0 && param1 <= MASK_01111111) {
            _loc2_.writeByte(param1)
            this.writeBytes(_loc2_)
            return
        }
        var _loc3_ = param1
        var _loc4_ = new ByteArray()
        while (_loc3_ !== 0) {
            _loc4_.writeByte(_loc3_ & MASK_01111111)
            _loc4_.position = _loc4_.length - 1
            _loc5_ = _loc4_.readByte()
            _loc3_ = _loc3_ >>> CHUNCK_BIT_SIZE
            if (_loc3_ > 0) {
                _loc5_ = _loc5_ | MASK_10000000
            }
            _loc2_.writeByte(_loc5_)
        }
        this.writeBytes(_loc2_)
    }
 
Inscrit
15 Avril 2020
Messages
6
Reactions
1
#10
Merci pour ton aide !
Je ne suis pas réellement sur de la provenance de mon erreur, étant donné que j'ai fait tellement tellement de changement, que je ne sais même plus ce qui a réglé mon problème ... Quoi qu'il en soit, j'en suis désormais à ce stade :

J'ai déjà commencé à me pencher dessus, et je sens que je vais pas mal galérer n'ayant jamais touché au RSA ahah
 
Haut Bas