Quand nous aurons nos blocs à l'unité, alors à ce moment là nous pourrons sauvegarder leur état, position, ...
Pour pouvoir "trancher" notre structure, nous allons utiliser des (3 en fait, vu que nous avons une structure tri-dimensionnelle) loop x times imbriquées, où le "x" correspond au nombre de couches composant notre structure.
Voici le principe de fonctionnement du code:
loop <x couches> times:
loop <y couches> times:
loop <z couches> times:
#Ici on sauvegardera la position RELATIVE du bloc, ainsi que le bloc en lui-même
[spoiler=Position relative ? Késako ?]Vous connaissez -j'espère- les coordonnées de Minecraft ? le X, le Y et le Z. Et bien lors de vos parties d'UHC où vous communiquez à vos amis ces nombres, ce sont en réalité les coordonnées ABSOLUES de votre position, c'est à dire que depuis n'importe où dans la map, on peut aisément se situer, ces coordonnées là ont comme origine le 0, 0, 0 de la map. Les coordonnés relatives, elles, ce serait plutôt comme dire 'Je me trouve 39 blocs à l'est, 6 blocs plus bas et 148 blocs au nord PAR RAPPORT à ta propre position". Les joueurs ayant beaucoup utilisés les blocs de commandes connaissent aussi les coordonnées relatives, le fameux tilde (~).
Vous vous demandez peut-être aussi pourquoi nous avons besoin de coordonnées relatives et non absolues; la raison est simple: ici, nous ne souhaitons pas de coordonnées absolues car elles sont justement absolues ! Or, nous ne devons connaitre que le positionnement des blocs de la structure les uns par rapport aux autres.
Pour connaitre la position relative d'un bloc, il me suffit maintenant de récupérer la loop-value-<1|2|3> des boucles !
Enfin, presque, un skripteur minutieux sait que la loop-value d'une boucle loop x times commence à partir de 1, or, moi je souhaite que le premier bloc soit en position relative 0, 0, 0. Il me faut donc soustraire 1 à mes loop-values.
Voici le code actuel:
loop <x couches> times:
loop <y couches> times:
loop <z couches> times:
#On définis les coordonnés corrects par rapport aux loop-values
set {_x} to "%loop-value-1%" parsed as number -1
set {_y} to "%loop-value-2%" parsed as number -1
set {_z} to "%loop-value-3%" parsed as number -1
Maintenant, nous allons compléter le début du code, histoire que ce soit clair dans vos têtes !
Pour connaitre la zone à enregistrer, nous avons besoin de seulement 2 coordonnées, de manière à former un parallélépipède rectangle. Pour rendre la sélection plus facile, on va sélectionner nos 2 coordonnées grâce à un item (ici une blaze rod) -à la manière de WorldEdit et de sa hache-. Voici le code que j'utilise:
[spoiler=Code]
on left click with blaze rod:
If name of player's tool is "Sélection":
if event-block is set:
cancel event
set {sktruc::sel1::x} to x-coordinate of event-block
set {sktruc::sel1::y} to y-coordinate of event-block
set {sktruc::sel1::z} to z-coordinate of event-block
send "Point 1: %{sktruc::sel1::x}% %{sktruc::sel1::y}% %{sktruc::sel1::z}%"
on right click with blaze rod:
If name of player's tool is "Sélection":
if event-block is set:
cancel event
set {sktruc::sel2::x} to x-coordinate of event-block
set {sktruc::sel2::y} to y-coordinate of event-block
set {sktruc::sel2::z} to z-coordinate of event-block
send "Point 2: %{sktruc::sel2::x}% %{sktruc::sel2::y}% %{sktruc::sel2::z}%"
Je récupère donc mes coordonnées (absolues) de mes 2 coins de la structure dans des variables.
[spoiler="C'est quoi {sktruc::[..]} ?"]Si j'utilise un préfix, car oui c'en est un (SKTRUCture), c'est pour que ce ne soit pas le bordel dans mes variables ! Imaginez que j'installe un skript qui n'est pas de moi sur mon serveur, et que ce skript n'ai pas de préfix et utilise les mêmes variables que moi ! Plus rien ne fonctionnerait correctement !
[spoiler=Et pourquoi tu n'utilise presque que des "::" ? Le . il existe aussi !]C'est exact, mais Skript étant ainsi fait que les "::" signifient une variable liste. Cela est d'un énorme avantage de les utiliser car elles permettent d'être manipulée comme des listes. Je peux donc, par exemple, supprimer le point 1 de ma sélection en une seule ligne (clear {sktruc::sel1::*}), alors que mettre un . n'apporte rien ! Si un jour je décide de supprimer seulement Sktructure de mon serveur, je peux aussi (par souci de perfection) supprimer toutes les variables qui y sont associées !
Une fois mes coordonnées obtenues, il me suffit de faire la soustraction, par exemple, de {sktruc::sel2::x} par {sktruc::sel1::x}, et j'obtient alors l'épaisseur en X de ma structure. On pourrait se dire que c'est bon comme ça; sauf que non. D'abord, il est fort probable que je ne sélectionne pas les plus petites coordonnées en "Point 1" et les plus grandes coordonnées en "Point 2", le problème étant que si je soustrait, par exemple, 98 à 72, le résultat sera négatif ! Le loop x times ne s’exécutera alors pas ! Il faut donc réordonner les paires de coordonnées.
Le second problème est plus subtil. Imaginons que nous avons sélectionné un bloc en coordonnées x=2 et l 'autre en x=5; le calcul 5-2 donne 3. Hors, si vous êtes un peu malin, vous savez qu'il y a 4 blocs d'épaisseur en X, x=2, x=3, x=4 et x=5. On peut vérifier ce fait en sélectionnant qu'une épaisseur, vous aurez alors 2-2=0, mais il y a une couche en vérité ! Il faut donc ajouter 1 à notre soustraction.
On va donc d'abord réordonner nos coordonnées, et en même temps vérifier qu'elles existent !:
if {struc::sel1::x} < {struc::sel2::x}:
set {_x1} to {sktruc::sel1::x}
set {_x2} to {sktruc::sel2::x}
else if {struc::sel1::x} > {struc::sel2::x}:
set {_x1} to {sktruc::sel2::x}
set {_x2} to {sktruc::sel1::x}
else:
send "Erreur"
stop
#Ce même code pour Y et Z
Et pour le +1 et la soustraction, on va l'intégrer aux loops:
loop {_x2} - {_x1} + 1 times:
loop {_y2} - {_y1} + 1 times:
loop {_z2} - {_z1} + 1 times:
set {_x} to "%loop-value-1%" parsed as number -1
set {_y} to "%loop-value-2%" parsed as number -1
set {_z} to "%loop-value-3%" parsed as number -1
#Reste du code à découvrir !
Maintenant, on va effectuer différents effets à chaque bloc de la structure, en connaissant leurs coordonnées relatives. Cependant, pour récupérer notre bloc, il va falloir convertir nos coordonnées relatives en coordonnées absolue. Pour cela, nous allons ajouter les coordonnées relatives de notre structure (ayant comme origine le bloc avec les plus petites coordonnées) au coordonnées absolues de ce même bloc ! On peut donc faire :
add location at {_x}, {_y}, {_z} to {sktruc::save::location::*} #Ici on enregistre les coordonnées relative du bloc
add type of block at location {_x}+{_x1}, {_y1}+{_y}, {_z1}+{_z} to {sktruc::save::block::*} #Et ici on enregistre de quel bloc il s'agit !
[spoiler=Heu.. Et comment on sait quels coordonnées correspondent à quel bloc ?]Et bien c'est très simple ! Étant donné que l'on enregistre en même temps la position du bloc et ses propriétés, leur index dans la liste est le même !
On peut aussi informer le joueur de la bonne sauvegarde de sa structure avec:
send "Structure sauvegardée."
send "Taille: x:%{_x2} - {_x1} +1% y:%{_y2} - {_y1} +1% z:%{_z2} - {_z1} +1%"
send "Points: x1:%{_x1}% y1:%{_y1}% z1:%{_z1}% x2:%{_x2}% y2:%{_y2}% z2:%{_z2}%"
On peut également ajouter
clear {sktruc::save::location::*}
clear {sktruc::save::block::*}
juste avant les loops, histoire qu'il n'y ai pas de bug de structure imbriquée.
Voilà, c'est tout, passons au "collage" de notre structure !
[spoiler=Code de la sauvegarde (et de la sélection)]
command /sktructuresave:
trigger:
if {sktruc::sel1::x} < {sktruc::sel2::x}:
set {_x1} to {sktruc::sel1::x}
set {_x2} to {sktruc::sel2::x}
else if {sktruc::sel1::x} > {sktruc::sel2::x}:
set {_x1} to {sktruc::sel2::x}
set {_x2} to {sktruc::sel1::x}
else:
send "Erreur"
stop
if {sktruc::sel1::y} < {sktruc::sel2::y}:
set {_y1} to {sktruc::sel1::y}
set {_y2} to {sktruc::sel2::y}
else if {sktruc::sel1::y} > {sktruc::sel2::y}:
set {_y1} to {sktruc::sel2::y}
set {_y2} to {sktruc::sel1::y}
else:
send "Erreur"
stop
if {sktruc::sel1::z} < {sktruc::sel2::z}:
set {_z1} to {sktruc::sel1::z}
set {_z2} to {sktruc::sel2::z}
else if {struc::sel1::z} > {sktruc::sel2::z}:
set {_z1} to {sktruc::sel2::z}
set {_z2} to {sktruc::sel1::z}
else:
send "Erreur"
stop
clear {sktruc::save::location::*}
clear {sktruc::save::block::*}
loop {_x2} - {_x1} + 1 times:
loop {_y2} - {_y1} + 1 times:
loop {_z2} - {_z1} + 1 times:
set {_x} to "%loop-value-1%" parsed as number -1
set {_y} to "%loop-value-2%" parsed as number -1
set {_z} to "%loop-value-3%" parsed as number -1
add location at {_x}, {_y}, {_z} to {sktruc::save::location::*}
add type of block at location {_x}+{_x1}, {_y1}+{_y}, {_z1}+{_z} to {sktruc::save::block::*}
send "Structure sauvegardée"
send "Taille: x:%{_x2} - {_x1} +1% y:%{_y2} - {_y1} +1% z:%{_z2} - {_z1} +1%"
send "Points: x1:%{_x1}% y1:%{_y1}% z1:%{_z1}% x2:%{_x2}% y2:%{_y2}% z2:%{_z2}%"
on left click with blaze rod:
If name of player's tool is "Selection":
if event-block is set:
cancel event
set {sktruc::sel1::x} to x-coordinate of event-block
set {sktruc::sel1::y} to y-coordinate of event-block
set {sktruc::sel1::z} to z-coordinate of event-block
send "Point 1: %{sktruc::sel1::x}% %{sktruc::sel1::y}% %{sktruc::sel1::z}%"
stop
on right click with blaze rod:
If name of player's tool is "Selection":
if event-block is set:
cancel event
set {sktruc::sel2::x} to x-coordinate of event-block
set {sktruc::sel2::y} to y-coordinate of event-block
set {sktruc::sel2::z} to z-coordinate of event-block
send "Point 2: %{sktruc::sel2::x}% %{sktruc::sel2::y}% %{sktruc::sel2::z}%"
stop
[spoiler=Optimisation du code...]Si vous avez suivi, dans ce bloc de code ci:
set {_x} to "%loop-value-1%" parsed as number -1
set {_y} to "%loop-value-2%" parsed as number -1
set {_z} to "%loop-value-3%" parsed as number -1
add location at {_x}, {_y}, {_z} to {sktruc::save::location::*}
add type of block at location {_x}+{_x1}, {_y1}+{_y}, {_z1}+{_z} to {sktruc::save::block::*}
Je parse mes différentes loop-values. Cependant, après des tests sur de plus grandes structures, cela rend le code horriblement lent ! De plus, je n'ai pas trouvé le moyen de faire autrement (voir :https://skript-mc.fr/forum/threads/loop-value-integer-number-non-reconnue.10038/#post-85436). Si vous pouvez m'aidez, ce serait bien gentil !
-Placer la structure à un autre endroit-
Pour ce faire, c'est très simple ! Nous allons d'abord créer une "loop {sktruc::save::location::*}:", nous reconvertirons les coordonnées relatives en coordonnées absolues, et nous irons chercher le type de bloc à poser grâce au loop-index, qui est, je rappelle, le même pour les coordonnées et le type d'un même bloc.
loop {sktruc::save::location::*}:
set {_x} to x-coordinate of loop-value + x-coordinate of player
set {_y} to y-coordinate of loop-value + y-coordinate of player
set {_z} to z-coordinate of loop-value + z-coordinate of player
set block at location {_x}, {_y}, {_z} to {sktruc::block::%loop-index%}
Et vous avez votre structure collé avec comme origine relative votre joueur !
[spoiler=Code du collage de structure]
command /sktructureload:
trigger:
loop {sktruc::save::location::*}:
set {_x} to x-coordinate of loop-value + x-coordinate of player
set {_y} to y-coordinate of loop-value + y-coordinate of player
set {_z} to z-coordinate of loop-value + z-coordinate of player
set block at location {_x}, {_y}, {_z} to {sktruc::save::block::%loop-index%}
-Résumé-
Ici, nous avons appris à sauvegarder une structure tridimensionnelle en Skript. On peut aussi y ajouter un support par joueur, une gestion des sauvegardes, ... On y a également vu comment récupérer notre structure précédemment enregistrée, et la coller de façon simple.
Je compte continuez de faire des tutos, en gardant notre Sktructure, l'améliorant et essayant de faire (pourquoi pas ^^) un WorldEdit-like. Si vous avez des idées, des suggestions, des remarques, des questions ou autre, n'hésitez pas à vous manifester !
Suite: Sktructure#2 Rotation et symétrie orthogonale
RebellCraft
thank for info!
___________________
free movies online