À compter du 4 septembre 2017, l'équipe de Minecraft Forge France ne fera plus aucun support pour la 1.7.10. La catégorie Cauldron sera archivée le même jour. Plus d'information ici

[1.7.10 -> 1.12] Synchroniser ses données avec DBSynchronizer
Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
#1
Idée 
Sommaire :
  • Introduction
  • Pré-requis
  • Tutoriel
    • Implémenter DBSynchronizer
    • Obtenir la base de données
    • Fonctionnement de la base de données et sauvegarde de données
  • Résultat final
  • Crédits
Introduction :

Bonjour à tous,
Dans ce tutoriel je vais vous apprendre à utiliser la library DBSynchronizer (Data Base Synchronizer) que j'ai conçu moi-même.
Cette library vous servira à simplifier grandement la synchronisation de données entre le serveur et le/les client(s) dans Minecraft. Cette library vous servira également à sauvegarder ces mêmes données dans la sauvegarde du monde.

Prenons un exemple :

Imaginez que vous créez un mod de magie que nous allons appeler Magikum et que vous avez besoin de stocker les données suivantes :
  • Le nombre de point de mana de chaque joueurs
  • Le niveau en magie de chaque joueurs : “apprenti”, “magicien” ou “grand sorcier”
  • La position des orbes qui sera reset a chaque fois qu'on relancera le monde (parce-que pourquoi pas ?)
Vous êtes donc conscient qu'il faudra sauvegarder dans la worldsave le nombre de point de mana de chaque joueur et le niveau en magie de chaque joueur.
Vous êtes aussi conscient qu'il faudra synchroniser toutes ces données afin que le serveur et chaque clients puissent y accéder en temps réel et les modifier.

Ça fait beaucoup à gérer pour pas grand chose n'est-ce pas ? D'autant plus si votre mod présente beaucoup d'éléments à synchroniser.
Et bien la library DBSynchronizer est faite pour vous !
Oui, ça fait un peu pub dit comme ça, mais bon, j'en suis fier de ma library.  Grand sourire

Pré-requis :

Il est nécessaire d'avoir créé la classe principale de son mod, un tuto est disponible sur le site.

Même si vous en aurez pas besoin ici, il est préférable d'avoir déjà manipulé les packets et d'avoir quelques notion sur le network. Un tuto est disponible sur le site.
De cette façon vous comprendrez mieux ce que vous faites (essayez au moins de lire le pré-requis).

Enfin, dans ce tutoriel je m'adresse à des personnes qui ont un niveau assez basique en java : il faut savoir ce qu'est un objet, connaitre les notions d'héritages et gérer les exceptions quand il y en a. Voici un cours OpenClassroom très complet (il est conseillé d'avoir lu les 2 premières parties).
Si vous n'avez pas ces notions vous pouvez quand même continuer mais dans ce cas je vous souhaite bon courage !

Ha, et n'hésitez pas à cliquer sur les images pour les agrandir Clin d'oeil

Tutoriel :

Implémenter DBSynchronizer :

    Pour la 1.7.10 :


Premièrement vous devez télécharger DBSynchronizer ici faites attentions à bien télécharger la version pour les développeurs.
Petite précision importante : les utilisateurs qui téléchargeront votre mod devront aussi télécharger DBSynchronizer mais cette fois, la version joueur.

Ensuite il faut que vous mettiez le jar que que vous venez de télécharger dans un dossier libs (et non pas lib) que vous aurez créé à la racine du projet afin que lors du build de votre mod, le gradle trouve bien les fichiers de la library.

[Image: package-explorer 1.7.10]

Pour finir, il faut paramétrer votre projet pour qu'il détecte DBSynchronizer comme étant une library. Pour cela, il faut faire clic droit sur votre projet (Minecraft) puis Properties → Java Build Path → Libraries → Add Jars...
Ensuite vous sélectionner : Minecraft/libs/DBSynchronizer.jar

[Image: lib-config 1.7.10]

Puis vous faites OK mais ne fermez pas la fenêtre tout de suite car il faut lier la javadoc. Pour ce faire il faut que vous cliquiez sur la petite flèche à coté de DBSynchronizer puis sur Javadoc location: (none) puis sur Edit... et dans Javadoc location path vous entrez l'url suivante : http://www.trcgames.com/dbsynchronizer/javadoc

[Image: javadoc-config]

Enfin cliquez sur OK puis à nouveau sur OK.

Voilà !
DBSynchronizer est maintenant bien implémenté à votre mod, vous pouvez désormais l'utiliser en toute tranquilité.

    Pour les autres versions :

Premièrement vous devez télécharger DBSynchronizer ici.

Ensuite il faut que vous mettiez le jar que que vous venez de télécharger dans le dossier mods, lui même situé dans le dossier run. En effet DBSynchronizer est un mod, donc les utilisateurs qui téléchargeront votre mod devront aussi télécharger DBSynchronizer et le mettre dans leur dossier mods.
Vous devez également mettre le jar dans un dossier libs que vous aurez créé à la racine du projet afin que lors du build de votre mod, le gradle trouve bien les fichiers de la library.

[Image: package-explorer]

Pour finir, il faut paramétrer votre projet pour qu'il détecte DBSynchronizer comme étant une library. Pour cela, il faut faire clic droit sur votre projet (MDKExample) puis Properties → Java Build Path → Libraries → Add Jars...
Ensuite vous sélectionner : MDKExample/run/mods/DBSynchronizer.jar

[Image: lib-config]

Puis vous faites OK mais ne fermez pas la fenêtre tout de suite car il faut lier la javadoc. Pour ce faire il faut que vous cliquiez sur la petite flèche à coté de DBSynchronizer puis sur Javadoc location: (none) puis sur Edit... et dans Javadoc location path vous entrez l'url suivante : http://www.trcgames.com/dbsynchronizer/javadoc

[Image: javadoc-config]

Enfin cliquez sur OK puis à nouveau sur OK.

Voilà !
DBSynchronizer est maintenant bien implémenté à votre mod, vous pouvez désormais l'utiliser en toute tranquilité.

Obtenir la base de données :

La base de données va vous servir à stocker des données qui seront ensuite automatiquement synchronisées (et sauvegardées si vous le souhaitez).
Pour récupérer l'instance de la base de données vous devez tout simplement faire :

DatabaseGetter.getInstance (modID);

modID étant l'ID de votre mod (merci captain obvious).
Cette fonction va vous retourner un objet Database qui pourra être une ServerDatabase ou une ClientDatabase, ça dépendra si vous vous trouverez du côté server ou du côté client mais dans tous les cas la façon de l'utiliser est la même.

Ce qu'il faut que vous sachiez, c'est que la base de donnée est liée à un monde. Cela vaut dire que vous ne pourrez pas l'obtenir si aucun monde n'est chargé (normal). Ce qui veut aussi dire que chaque monde aura sa propre base de données.
Donc si une exception est lancé quand vous quand vous récupérez la base de données c'est peut-être qu'aucun monde n'est chargé à ce moment là.

Petite parenthèse :
Citation :Ne castez pas l'instance de la base de données en ClientDatabase ou en ServerDatabase car ça vous donnerait accès à des méthodes dont vous ne devriez pas y avoir l'accès. Les manipuler pourrait aller jusqu'à corrompre une sauvegarde, désynchroniser les clients/server ou faire freeze le server (je vous aurait prévenu  Clin d'oeil ).

Dernières restrictions :
Vous ne pouvez pas obtenir la base de données depuis un Thread que vous aurez créé, même si ça a l'air de fonctionner, ne le faites pas. (désolé mais peut être que dans les prochaines versions ça changera).
Et évitez de stocker l'instance dans un variable de classe, exemple :

import com.trcgames.dbSynchronizer.DatabaseGetter;
import com.trcgames.dbSynchronizer.database.Database;

public class Exemple {
    
    //fortement déconseillé
    private Database database = DatabaseGetter.getInstance (Magikum.MODID);
    
    public void methode (){
        
        //correcte
        Database database = DatabaseGetter.getInstance (Magikum.MODID);
    }
}

Fonctionnement de la base de données et sauvegarde de données :

C'est bien beau d'avoir une base de données mais maintenant il faut savoir comment l'utiliser !
Pour ça, vous devez d'abord comprendre ce qu'est un DBFolder.

Un DBFolder est un objet qui pourra stocker plein de types de variables différentes, mais aussi d'autres DBFolder. En fait, un DBFolder c'est un peu comme un NBTTagCompound.

Vous pouvez stocker/modifier des données avec une clé :

DBFolder folder = new DBFolder ();

folder.setInt ("mon entier", 42);
folder.setBoolean ("mon booléen", true);
folder.setBlockPos ("ma position", new BlockPos (34, 70, -20));
//etc...

Vous pouvez aussi les récupérer en utilisant la clé :

int monEntier = folder.getInt ("mon int");
boolean monBooleen = folder.getBoolean ("mon booléen");
BlockPos maPosition = folder.getBlockPos ("ma position");
//etc..

Voir même les supprimer, toujours en utilisant la clé :

folder.removeInt ("mon int");
folder.removeBoolean ("mon booléen");
folder.removeBlockPos ("ma position");
//etc...

Il est possible d'utiliser la même clé pour deux données différentes du moment que les données ne sont pas du même type.

Si vous ne l'avez pas déjà compris, c'est en fait ce qui vous servira à stocker des données comme, le nombre de point de mana de chaque joueurs, le niveau en magie de chaque joueurs et la position des orbes.
C'est cool non ? C'est normal c'est moi qui l'ai fait.  Grand sourire

Et bien devinez quoi ?
La base de donnée vous donne accès à deux DBFolder que vous pourrez modifier à votre guise.

Vous pouvez obtenir un DBFolder dont le contenu sera sauvegardé quand on quittera le monde avec getPersistentFolder() et un autre dont le contenu ne sera pas sauvegardé avec getNonPersistentFolder().

Database database = DatabaseGetter.getInstance (Magikum.MODID);
DBFolder dossierPersistant = database.getPersistentFolder();
DBFolder dossierNonPersistant = database.getNonPersistentFolder();

Pour que ça soit plus clair pour vous, reprenons notre exemple du mod Magikum.
On pourrait architecturer notre base de données de cette manière :

[Image: arbre]

Ce qui donnerait au niveau du code :

Database database = DatabaseGetter.getInstance (Magikum.MODID);
DBFolder dossierPersistant = database.getPersistentFolder();
DBFolder dossierNonPersistant = database.getNonPersistentFolder();

DBFolder pointsDeMana = new DBFolder ();
dossierPersistant.setDBFolder ("points de mana", pointsDeMana); // vu qu'on fait un "set", si le DBFolder "points de mana" existe déjà, alors il sera remplacé
pointsDeMana.setInt ("TheRedColossus", 30);
pointsDeMana.setInt ("cpw", 96);
pointsDeMana.setInt ("Notch", 9000);

DBFolder niveau = dossierPersistant.getDBFolder ("niveau"); // cette fois ci on fait un "get", donc si le DBFolder "niveau" n'existe pas encore, alors il sera créé et stocké
niveau.setString ("TheRedColossus", "apprenti");
niveau.setString ("cpw", "magicien");
niveau.setString ("Notch", "grand sorcier");

dossierNonPersistant.setBlockPos ("orbe de lumière", new BlockPos (-254, 127, 50));
dossierNonPersistant.setBlockPos ("orbe obscure", new BlockPos (1038, 68, 547));
dossierNonPersistant.setBlockPos ("orbe de puisssance", new BlockPos (-102, 5, -10));

Voilà, c'est tout !
C'est tout ?

Oui, effectivement, toutes les données qui seront stockées sur la base de données seront automatiquement sauvegardées si elles se situes dans le persistentFolder, que vous soyez côté server ou client. D'autant plus, à chaque fois que vous ajouterez, modifierez ou supprimerez une donnée, ce sera synchronisé avec le server et tous les clients.
Ça veut dire que si vous modifiez la position d'une orbe depuis un client, la modification sera prise en compte sur le server puis sur tous les autres clients dans les centièmes de seconde qui vont suivre. Donc si ensuite vous récupérez la positions de l'orbe depuis le server ou un autre client (si vous êtes en multijoueurs) la modification aura été prise en compte.
On ne peut pas faire plus simple !

Résultat final :

Si vous avez envi de savoir ce qu'il y a dans un DBFolder (pour débugger par exemple), vous pouvez utiliser la méthode printInConsole :

DBFolder folder = new DBFolder ();
folder.printInConsole (true); // Mettez true si votre console supporte les caractères unicodes sinon mettez false.

Ce qui donne pour notre persistentFolder :

Code :
(DBFolder) persistent folder
├(DBFolder) point de mana
│├(int) TheRedColossus : 30
│├(int) cpw : 96
│└(int) Notch : 9000
└(DBFolder) niveau
 ├(String) TheRedColossus : apprenti
 ├(String) cpw : magicien
 └(String) Notch : grand sorcier

et pour notre nonPersistentFolder :

Code :
(DBFolder) non-persistent folder
├(BlockPos) orbe de lumière : x=-254 y=127 z=50
├(BlockPos) orbe obscure : x=1038 y=68 z=547
└(BlockPos) orbe de puisssance : x=-102 y=5 z=-10

Sur ce, merci d'avoir suivit ce tutoriel, j'espère que ma library vous sera utile !
Pour ce qui est des questions, n'hésitez pas à les poser, et si vous trouvez des bugs sur ma library, je serais très reconnaissant que vous m'en avertissiez. Et au contraire, si la library fonctionne parfaitement ça me serait aussi utile que vous me le dîtes.

Crédits :

TheRedColossus
Répondre
#2
Salut !
J'ai fait comme tu as dis.
Le client se lance sans problème mais pas le serveur qui, d'après les logs, fini par :
https://pastebin.com/GZZ5cSkt
Je suis un membre apprécié et joueur, j'ai déjà obtenu 5 point(s) de réputation.

J'ai et je suis triste d'avoir 12 points d'ICRating

Répondre
#3
Ok je m'occupe de ça. Je te dis quand j'ai trouvé.
Est-ce que tu peux me montre ton code ?
Répondre
#4
En fait, j'ai juste fait la base du mon mod (Annotation Mod + Proxy). J'ai juste installer le Synchroniser mais je ne l'utilise pas dans le code.
Je suis un membre apprécié et joueur, j'ai déjà obtenu 5 point(s) de réputation.

J'ai et je suis triste d'avoir 12 points d'ICRating

Répondre
#5
Est-ce que tu peux me faire un screenshot du package explorer pour que je vois comment tu l'as installé ?
Répondre
#6
Le voici : https://puu.sh/wOmxr/5f2ea70ecc.png
Je suis un membre apprécié et joueur, j'ai déjà obtenu 5 point(s) de réputation.

J'ai et je suis triste d'avoir 12 points d'ICRating

Répondre
#7
Je n'ai pas pris en compte le fait que il y a eu beaucoup de changements après la 1.7.10
Du coup la version de DBSynchronizer pour la 1.7.10 est complètement bugée et même la façon dont on doit l'installer est différente (du coup le tutoriel ne colle pas trop pour la 1.7.10).

Je vais essayer de régler ça rapidement. Désolé du désagrément.
Répondre
#8
Okay merci, je vais attendre du coup
Je suis un membre apprécié et joueur, j'ai déjà obtenu 5 point(s) de réputation.

J'ai et je suis triste d'avoir 12 points d'ICRating

Répondre
#9
Voilà !
En fait pour la 1.7.10 c'est un peu particulié, il y a une version de DBSynchronizer pour les joueurs et une autre pour les développeurs.
Je te laisse suivre à nouveau la partie installation du tutoriel car c'est complètement différent pour la 1.7.10.

Merci de ta patience !
Répondre
#10
Okay merci, je reviens si j'ai des problèmes Sourire

EDIT : Ca fonctionne nickel. Petite question : si on met ce mod sur serveur, il faut aussi prendre la version pour joueur ?
Je suis un membre apprécié et joueur, j'ai déjà obtenu 5 point(s) de réputation.

J'ai et je suis triste d'avoir 12 points d'ICRating

Répondre


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)