Clone Minecraft pour Windows, Mac OS X et Linux. Juste quelques milliers de lignes de C utilisant OpenGL moderne (shaders). La prise en charge multijoueur en ligne est incluse à l'aide d'un serveur basé sur Python.
http://www.michaelfogleman.com/craft/
Les binaires Mac et Windows sont disponibles sur le site Web.
http://www.michaelfogleman.com/craft/
Voir ci-dessous pour exécuter à partir des sources.
Téléchargez et installez CMake si vous ne l'avez pas déjà. Vous pouvez utiliser Homebrew pour simplifier l'installation :
brew install cmake
sudo apt-get install cmake libglew-dev xorg-dev libcurl4-openssl-dev
sudo apt-get build-dep glfw
Téléchargez et installez CMake et MinGW. Ajoutez C:MinGWbin
à votre PATH
.
Téléchargez et installez cURL pour que CURL/lib et CURL/include se trouvent dans votre répertoire Program Files.
Utilisez les commandes suivantes à la place de celles décrites dans la section suivante.
cmake -G "MinGW Makefiles"
mingw32-make
Une fois que vous avez les dépendances (voir ci-dessus), exécutez les commandes suivantes dans votre terminal.
git clone https://github.com/fogleman/Craft.git
cd Craft
cmake .
make
./craft
Après de nombreuses années, craft.michaelfogleman.com a été supprimé. Voir la section Serveur pour plus d'informations sur l'auto-hébergement.
Vous pouvez vous connecter à un serveur avec des arguments de ligne de commande...
./craft [HOST [PORT]]
Ou, avec la commande "/online" dans le jeu lui-même.
/online [HOST [PORT]]
Vous pouvez exécuter votre propre serveur ou vous connecter au mien. Le serveur est écrit en Python mais nécessite une DLL compilée pour pouvoir effectuer la génération du terrain tout comme le client.
gcc -std=c99 -O3 -fPIC -shared -o world -I src -I deps/noise deps/noise/noise.c src/world.c
python server.py [HOST [PORT]]
/goto [NAME]
Téléportez-vous vers un autre utilisateur. Si NOM n'est pas spécifié, un utilisateur aléatoire est choisi.
/list
Afficher une liste des utilisateurs connectés.
/login NAME
Passez à un autre nom d'utilisateur enregistré. Le serveur de connexion sera recontacté. Le nom d'utilisateur est sensible à la casse.
/logout
Annulez votre authentification et devenez un utilisateur invité. Les connexions automatiques ne se reproduiront plus tant que la commande /login ne sera pas réexécutée.
/offline [FILE]
Passez en mode hors ligne. FILE spécifie le fichier de sauvegarde à utiliser et la valeur par défaut est "craft".
/online HOST [PORT]
Connectez-vous au serveur spécifié.
/pq P Q
Téléportez-vous vers le morceau spécifié.
/spawn
Téléportez-vous au point d'apparition.
Le terrain est généré à l'aide du bruit Simplex, une fonction de bruit déterministe basée sur la position. Le monde sera donc toujours généré de la même manière dans un lieu donné.
Le monde est divisé en blocs de 32 x 32 dans le plan XZ (Y est en haut). Cela permet au monde d'être « infini » (la précision en virgule flottante est actuellement un problème pour les grandes valeurs X ou Z) et facilite également la gestion des données. Seuls les morceaux visibles doivent être interrogés dans la base de données.
Seules les faces exposées sont rendues. Il s'agit d'une optimisation importante car la grande majorité des blocs sont soit complètement cachés, soit n'exposent qu'une ou deux faces. Chaque morceau enregistre un chevauchement d'une largeur d'un bloc pour chaque morceau voisin afin de savoir quels blocs le long de son périmètre sont exposés.
Seuls les morceaux visibles sont rendus. Une approche naïve d'élimination du tronc est utilisée pour tester si un morceau est dans le champ de vision de la caméra. Si ce n'est pas le cas, il n'est pas rendu. Cela se traduit également par une amélioration des performances assez décente.
Les tampons de bloc sont complètement régénérés lorsqu'un bloc est modifié dans ce bloc, au lieu d'essayer de mettre à jour le VBO.
Le texte est rendu à l'aide d'un atlas bitmap. Chaque caractère est rendu sur deux triangles formant un rectangle 2D.
OpenGL « moderne » est utilisé – aucune fonction de pipeline obsolète à fonction fixe n’est utilisée. Les objets tampon Vertex sont utilisés pour les coordonnées de position, normales et de texture. Les vertex shaders et fragment shaders sont utilisés pour le rendu. Les fonctions de manipulation matricielle sont dans Matrix.c pour les matrices de translation, de rotation, de perspective, orthographiques, etc. Les modèles 3D sont constitués de primitives très simples – principalement des cubes et des rectangles. Ces modèles sont générés en code dans cube.c.
La transparence dans les blocs de verre et les plantes (les plantes ne prennent pas la forme rectangulaire complète de leurs primitives triangulaires) est implémentée en supprimant les pixels de couleur magenta dans le fragment shader.
Les modifications apportées par les utilisateurs au monde sont stockées dans une base de données SQLite. Seul le delta est stocké, donc le monde par défaut est généré, puis les modifications utilisateur sont appliquées par-dessus lors du chargement.
La table principale de la base de données est nommée « bloc » et comporte les colonnes p, q, x, y, z, w. (p, q) identifie le morceau, (x, y, z) identifie la position du bloc et (w) identifie le type de bloc. 0 représente un bloc vide (air).
Dans le jeu, les morceaux stockent leurs blocs dans une carte de hachage. Une clé (x, y, z) correspond à une valeur (w).
La position y des blocs est limitée à 0 <= y < 256. La limite supérieure est principalement une limitation artificielle visant à empêcher les utilisateurs de construire des structures inutilement hautes. Les utilisateurs ne sont pas autorisés à détruire les blocs à y = 0 pour éviter de tomber sous le monde.
Le mode multijoueur est implémenté à l’aide de sockets classiques. Un protocole simple, ASCII, basé sur des lignes, est utilisé. Chaque ligne est composée d'un code de commande et de zéro ou plusieurs arguments séparés par des virgules. Le client demande des fragments au serveur avec une simple commande : C,p,q,key. « C » signifie « Chunk » et (p, q) identifie le morceau. La clé est utilisée pour la mise en cache - le serveur enverra uniquement les mises à jour de bloc qui ont été effectuées depuis la dernière demande du client pour ce morceau. Les mises à jour de blocs (en temps réel ou dans le cadre d'une requête de bloc) sont envoyées au client au format : B,p,q,x,y,z,w. Après avoir envoyé tous les blocs pour un morceau demandé, le serveur enverra une clé de cache mise à jour au format : K,p,q,key. Le client stockera cette clé et l'utilisera la prochaine fois qu'il aura besoin de demander ce morceau. Les positions des joueurs sont envoyées au format : P,pid,x,y,z,rx,ry. Le pid est l'identifiant du joueur et les valeurs rx et ry indiquent la rotation du joueur sur deux axes différents. Le client interpole les positions des joueurs à partir des deux dernières mises à jour de position pour une animation plus fluide. Le client envoie sa position au serveur au maximum toutes les 0,1 secondes (moins s'il ne bouge pas).
La mise en cache côté client dans la base de données SQLite peut être gourmande en performances lors de la première connexion à un serveur. Pour cette raison, les écritures SQLite sont effectuées sur un thread en arrière-plan. Toutes les écritures se produisent dans une transaction pour des raisons de performances. La transaction est validée toutes les 5 secondes, par opposition à une quantité logique de travail effectué. Un tampon en anneau/circulaire est utilisé comme file d'attente pour les données à écrire dans la base de données.
En mode multijoueur, les joueurs peuvent s'observer dans la vue principale ou dans une vue image dans l'image. La mise en œuvre du PnP a été étonnamment simple : il suffit de changer la fenêtre et de restituer à nouveau la scène du point de vue de l'autre joueur.
Le test de frappe (le bloc vers lequel l'utilisateur pointe) est mis en œuvre en balayant un rayon depuis la position du joueur vers l'extérieur, en suivant son vecteur de visée. Il ne s'agit pas d'une méthode précise, le taux de pas peut donc être réduit pour être plus précis.
Les tests de collision ajustent simplement la position du joueur pour rester à une certaine distance de tout bloc adjacent qui constitue un obstacle. (Les nuages et les plantes ne sont pas marqués comme des obstacles, vous les traversez donc.)
Un dôme céleste texturé est utilisé pour le ciel. La coordonnée X de la texture représente l'heure de la journée. La carte des valeurs Y du bas de la sphère du ciel au sommet de la sphère du ciel. Le joueur est toujours au centre de la sphère. Les shaders de fragments pour les blocs échantillonnent également la texture du ciel pour déterminer la couleur de brouillard appropriée avec laquelle se fondre en fonction de la position du bloc par rapport au ciel d'arrière-plan.
L'occlusion ambiante est implémentée comme décrit sur cette page :
http://0fps.wordpress.com/2013/07/03/ambient-occlusion-for-minecraft-like-worlds/