4 votes

Minecraft 1.14.4 tableau d'entiers de taille dynamique

Je suis en train d'essayer de créer un tableau d'entiers de taille dynamique dans Minecraft 1.14.4. J'ai déjà essayé différentes méthodes, mais le problème avec toutes ces solutions, c'est que je devais invoquer une entité pour chaque index, puis avoir deux tableaux de bord, qui contenaient l'entier pour chaque entité et l'index pour chaque entité.

Ensuite, je devais exécuter quelque chose comme ceci :

/execute as @e[type=minecraft:armor_stand,tag=array] if score #index INDEX = @s INDEX store result score #value VALUES run scoreboard players get @s VALUES

#index est l'index que je veux lire, et #value est la valeur de retour. Le problème avec cela, c'est que si vous avez environ 1000 index, le jeu devient vraiment lent en raison de toutes les entités.

Est-ce que quelqu'un a une idée de comment faire cela d'une meilleure façon? Peut-être avec la possibilité des tableaux nbt 1.14, mais sans avoir besoin d'itérer à travers chaque index (parce que chaque commande prend du temps à s'exécuter, et j'ai nécessairement besoin de vitesse)?

PS : J'utilise déjà un datapack, donc ce ne sera pas un problème si la solution dépend des fonctions.

0 votes

Donc vous voulez définir la longueur d'un tableau en fonction d'une valeur du tableau de bord ? Mais avec quoi rempliriez-vous ce tableau ? Il est probablement plus facile que la longueur soit automatiquement définie lors de la définition des valeurs.

0 votes

Non seulement avoir la longueur définie par un tableau des scores, mais aussi lire à partir d'une position variable dans le tableau, définie dans un tableau des scores

0 votes

Lorsque j'ai lu cette question pour la première fois, j'ai pensé "pourquoi auriez-vous même besoin de cela?", mais maintenant j'ai référencé ma réponse à celle-ci dans au moins trois endroits différents, dans des contextes complètement différents.

3voto

Fabian Röling Points 19325

La création d'un tableau de taille dynamique dans NBT est assez simple : il suffit d'utiliser une fonction récursive pour boucler sur un score (qui détermine la longueur) et d'utiliser /data modify [...] append à chaque fois. Voici un exemple :

Configuration :

/scoreboard objectives add array dummy
/scoreboard players set $value array 1
/scoreboard players set $length array 10
/scoreboard players set $const2 array 2
/data merge storage fabian:array {array:[]}

J'utilise une multiplication par 2 à chaque itération pour montrer que vous pouvez effectuer des calculs arbitraires avec les valeurs.

Fonction "fabian:fill_array" :

execute store result storage fabian:array value int 1 run scoreboard players get $value array
data modify storage fabian:array array append from storage fabian:array value
scoreboard players operation $value array *= $const2 array
scoreboard players remove $length array 1
execute if score $length array matches 0.. run function fabian:fill_array

Explication :
La première commande copie la valeur du tableau de bord du joueur factice "$value" dans l'étiquette NBT "value" dans le stockage.
La deuxième commande appose l'étiquette actuelle "value" sur le tableau. Il n'y a pas de moyen d'ajouter directement une valeur de tableau de bord à un tableau NBT.
Le reste de la fonction effectue simplement un calcul arbitraire sur "$value", décrémente "$length" et boucle jusqu'au début tant que "$length" n'a pas encore atteint 0.

Notez que cette fonction effectuera tout de même son calcul une fois et l'ajoutera au tableau, même si "$length" est déjà à 0 ou moins. Vous devriez en tenir compte dans le système que vous utilisez.


Passons maintenant à la partie plus compliquée : la lecture à partir d'un index arbitraire. Il existe deux principales façons de le faire.

La méthode fastidieuse : Avoir une grande fonction avec chaque possibilité qui pourrait se produire dans votre configuration :

execute if score $index array matches 0 run data get storage fabian:array array[0]
execute if score $index array matches 1 run data get storage fabian:array array[1]
execute if score $index array matches 2 run data get storage fabian:array array[2]
execute if score $index array matches 3 run data get storage fabian:array array[3]
…

Bien sûr, cela serait inapplicable pour des tableaux très longs.

La méthode de copie + suppression : Quelque chose de similaire a été suggéré ici (archive), mais ma méthode ne nécessite pas d'écrire l'index dans le tableau NBT, donc vous pouvez l'utiliser sur des données déjà existantes (créées par exemple par le jeu ou par un autre datapack).

Tout d'abord, copiez le tableau entier quelque part ailleurs :

/data modify storage fabian:array copie set from storage fabian:array array

Ensuite, retirez la première entrée du tableau autant de fois que vous le souhaitez (indiqué par exemple par un tableau de bord) :

/data remove storage fabian:array copie[0]

Une fois votre boucle terminée, lisez simplement la valeur de la première entrée qui reste :

/data get storage fabian:array copie[0]

Vous pouvez aussi faire ceci à l'envers, par exemple si vous voulez lire la nième dernière entrée dans un tableau, exécutez /data remove […] copie[-1] n-1 fois et ensuite /data get […] copie[-1].

Cela peut également être utilisé pour la recherche. Augmentez un tableau de bord d'index chaque fois que vous supprimez la première entrée et comparez la valeur à un tableau de bord de cette manière :

/execute store result storage fabian:array temp int 1 run scoreboard players get […]
/execute store success score $changed array run data modify storage fabian:array copie[0] set from storage fabian:array temp

Le joueur fictif "$changed" aura maintenant un 1 dans le tableau de bord array si la valeur actuelle du tableau est différente de celle que vous comparez et 0 si elle est la même (donc vous avez trouvé la valeur que vous recherchiez).
Le tableau de bord augmenté indique ensuite l'index. Alternativement, vous pouvez obtenir la longueur du tableau restant comme ceci :

/execute store result score $length array if data storage fabian:array array[]

Et ensuite vous pouvez soustraire cela de la longueur d'origine.

0 votes

First: merci pour la réponse, c'est peut-être une bonne façon de le faire. deuxième: y a-t-il un meilleur moyen que de parcourir tout le tableau et de lire directement à partir d'une position spécifique?

0 votes

J'ai supprimé mon commentaire du 2020-02-29 00:56, voici une copie avec le lien remplacé. Non, il n'y a pas d'autre moyen, sauf la "méthode fastidieuse". Au fait, j'aurais dû le lier de toute façon: j'ai diffusé en direct ma réponse à cette question et une autre question de gamingSE. Voici l'archive de la diffusion, vous pouvez voir mon processus de réflexion complet (j'espère) qui a eu lieu ici: youtube.com/watch?v=Y2Dev-Kzo-c

1 votes

La méthode inverse est en réalité préférée même si vous indexez à partir du début de la liste. Cela est dû au fait que lorsque vous retirez un élément de devant, le système doit déplacer tous les autres éléments vers l'avant. Lorsque vous retirez un élément de derrière, cela n'est pas nécessaire. Lorsque vous travaillez avec un index basé sur l'avant, il est plus efficace de calculer l'index inverse en utilisant la longueur de la liste et d'utiliser la méthode inverse à la place.

AlleGamers.com

AlleGamers est une communauté de gamers qui cherche à élargir la connaissance des jeux vidéo.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X