J'ai besoin d'utiliser un sélecteur d'entité dans une commande /exécution pour sélectionner tous les bateaux qui ont au moins un joueur à bord qui tient un objet spécifique. Cependant, parce que le id
n'existe pas pour les joueurs, aucun argument de sélection d'entité n'existe pour sélectionner une entité avec des passagers spécifiques, et je ne peux pas les sélectionner par la balise type
Comme les passagers d'une entité arbitraire ne peuvent être sélectionnés que par leurs données NBT, je ne peux pas sélectionner les montages avec des passagers de joueurs spécifiques en utilisant un sélecteur d'entité. Existe-t-il une solution de contournement pour cela ?
Réponses
Trop de publicités?Minecraft n'a pas de méthode appropriée pour comparer les NBT de deux entités. Vous devez donc choisir une des nombreuses solutions de contournement possibles, chacune ayant ses propres inconvénients.
La méthode la plus simple : Sélectionnez un joueur qui se trouve aux coordonnées prévues :
/execute at @e[type=boat] positioned ~ ~-.45 ~ if entity @p[distance=..1,nbt={SelectedItem:{id:"minecraft:stone"}}] run <command>
Cela présente plusieurs inconvénients :
- Il est dépendant du décalage et du mouvement. Si vous conduisez un bateau rapidement sur de la glace bleue et que vous avez un peu de retard, cette commande ne vous correspondra pas, même si vous êtes assis dans le bateau.
- Une personne se trouvant sur ou à côté du bateau peut également être sélectionnée. Pour éviter cela, vous pourriez réduire le rayon, mais cela amplifierait votre problème de dépendance au lag.
- Le décalage exact dépend du véhicule, vous devez donc déterminer un nouveau décalage si vous voulez faire de même pour les charrettes de mine, par exemple.
- Il faut le faire trois fois, une fois pour un seul passager, une fois pour le premier et une fois pour le deuxième passager d'un bateau avec deux passagers. (Le déplacement en avant ou en arrière par rapport au bateau peut être effectué à l'aide de "coordonnées locales" :
^ ^ ^
)
La méthode exacte : Je n'ai pas pu trouver une méthode qui ne boucle pas à la fois sur tous les bateaux et tous les joueurs, donc cela doit être fait dans une fonction.
D'abord, vous stockez une partie de l'UUID du véhicule racine de chaque joueur dans un tableau d'affichage. Vous pourriez le faire avec l'UUID complet, si vous le souhaitez, mais c'est beaucoup plus compliqué (cela pourrait nécessiter une recherche binaire), je ne montrerai donc que la méthode permettant de stocker une partie de celui-ci :
/execute as @a store result score @s vehicle run data get entity @s RootVehicle.Entity.UUIDMost 0.00000000023283064365386962890625
Ce facteur d'échelle est 2^-32, ce qui garantit que chaque valeur possible de UUIDMost
s'insère dans la partition en coupant la moitié inférieure.
Même si vous avez un bateau dans chaque bloc jusqu'à la distance de rendu 32, la probabilité de faire correspondre le mauvais bateau n'est que de 0,025 %, donc cette méthode devrait convenir.
Maintenant, faites la même chose pour l'UUID de tous les bateaux, mais sur leurs propres scores :
/execute as @e[type=boat] store result score @s vehicle run data get entity @s UUIDMost 0.00000000023283064365386962890625
Comparer et faire quelque chose pour chaque bateau qui a le même score dans ce tableau de bord qu'un joueur avec certaines propriétés est la partie compliquée.
Exécuter une fonction as
y at
chaque joueur détenant l'objet (ou remplissant une condition quelconque) :
/execute as @a[nbt={SelectedItem:{id:"minecraft:stone"}}] at @s run function test:vehicle
Il fonctionnerait également sans at
mais si vous utilisez at
Dans la plupart des cas, un seul bateau doit être contrôlé.
Le contenu de cette fonction :
function test:vehicle_loop
tag @e[type=boat] remove checked
say @e[type=boat,tag=found]
tag @e[type=boat] remove found
Cette fonction appelle une fonction qui boucle sur tous les bateaux et finit par trouver un seul bateau étiqueté " found
"Il nettoie ensuite (ce qui est important, si vous voulez le faire fonctionner pour plusieurs joueurs en une seule fois) et vous donne l'opportunité de faire quelque chose avec le bateau (encore as
le joueur, au cas où cela serait important).
Le contenu de la fonction vehicle_loop
:
execute if score @e[type=boat,tag=!checked,sort=nearest,limit=1] vehicle = @s vehicle run tag @e[type=boat,tag=!checked,sort=nearest,limit=1] add found
tag @e[type=boat,tag=!checked,sort=nearest,limit=1] add checked
execute unless entity @e[type=boat,tag=found] if entity @e[type=boat,tag=!checked] run function test:vehicle_loop
Cette fonction vérifie d'abord si le vehicle
Le score du bateau le plus proche du joueur qui n'a pas encore été contrôlé est le même que celui du bateau qui a été contrôlé. vehicle
le score du joueur. Si c'est le cas, vous avez réussi à trouver le bateau chevauché par ce joueur, et il sera marqué par " found
". Ensuite, le bateau est étiqueté avec " checked
", peu importe si c'est le bon ou pas. Puis la fonction s'appelle elle-même s'il reste des bateaux à vérifier (c'est ainsi que les boucles sont faites dans les fonctions).
Vous ne pouvez pas sélectionner une entité avec passagers spécifiques, mais vous pouvez sélectionner une entité sans des passagers spécifiques.
Vous pouvez créer des bateaux nommés et sélectionner ceux qui n'ont pas d'entité spécifique comme passager.
/summon minecraft:boat ~ ~ ~ {CustomName:"\"mcboat\"",Passengers:[{id:"minecraft:villager",CustomName:"\"boaty\""}]}
/summon minecraft:boat ~ ~ ~ {CustomName:"\"mcboat\""}
/kill @e[name="mcboat",nbt=!{Passengers:[{id:"minecraft:villager"}]}]
Malheureusement, je n'arrive à le faire fonctionner qu'en triant les passagers par id et non par une autre balise comme le nom. Je l'utilise pour m'assurer que mes villageois cavaliers restent sur leur cheval. J'utilise la version 1.14.4.
0 votes
C'est très difficile. Vous ne pouvez savoir ce qui monte et ce qui descend qu'en utilisant la fonction
RootVehicle
du joueur, mais vous ne pouvez pas modifier les données du joueur, même pour le véhicule racine, vous ne pouvez pas facilement comparer le NBT de deux entités,