Récupéré les BlockFace en fonction de la position que l'on casse un blocs

Kenda

Architecte en herbe
16 Juillet 2016
292
1
2
125
32
www.youtube.com
Bonjour,

Actuellement en train de crée un système de hammer, je cherche à récupéré les BlockFace en fonction de ou le joueurs casse le blocs.
Par exemple, si le BlockFace est Nord ou sud, il se casse bien en 3 x 3, mais pour le Est ou West, je sais pas trop comment faire?

Une petite aide svp ? merci :)
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 125
161
460
247
21
Mìlhüsa
Bonsoir,

Si tu vises la 1.14+, tu peux récupérer la face du bloc que le joueur a utilisé pour détruire celui-ci à coup de ray tracing.

Pour savoir dans quel sens orienter ton carré 3x3 qui détruit les blocs alentours, le code n'est pas très compliqué en soit mais c'est un peu chiant à visualiser ; l'idée est de parler des coordonnées non pas sur directement sur les axes (X, Y, Z) mais sur des axes intermédiaires (Longueur, Hauteur, Profondeur).
Par exemple, « le bloc situé à un bloc à droite du bloc détruit » sera noté « + 1 en longueur » et vaudra soit « + 1 en x » soit « + 1 en z » selon la direction.

Java:
public class HammerHandler implements Listener {
   // haute priorité : on laisse les autres plugins passer avant,
   // leur laissant le champ libre pour annuler l'évènement ;
   // si un plugin de protection (WorldGuard) est présent, il annulera l'évènement,
   // et notre fonction ne sera jamais appelée : si le bloc initial n'est pas détruit,
   // ceux autours ne doivent pas l'être.
   @EventHandler(priority = EventPriority.HIGHEST)
   public void onBlockBreak(BlockBreakEvent e) {
      Player player = e.getPlayer();
      ItemStack tool = player.getInventory().getItemInMainHand();
    
      if(!isMyHammer(tool)) {
         return; // pas notre outil
      }
    
      Block block = e.getBlock();
    
      final double breakRange = player.getGameMode() == GameMode.CREATIVE ? 5 : 4.5;
      Location playerPos = player.getLocation();
      Location eyePos = player.getEyeLocation();
    
      RayTraceResult ray = player.getWorld().rayTraceBlocks(eyePos, playerPos.getDirection(), breakRange, FluidCollisionMode.NEVER, true);
      BlockFace face;
      if(ray == null || ray.getHitBlock() == null || !ray.getHitBlock().equals(block) || (face = ray.getHitBlockFace()) == null) {
         return;
      }
    
      // l'axe de la face
      Axis faceAxis = getAxis(face);
    
      // la configuration de l'outil
      final int width = 5; // cinq blocs de longueur (à droite/à gauche du bloc)
      final int height = 3; // trois blocs de hauteur (en haut/en bas du bloc)
      final int depth = 1; // un bloc de profondeur (devant/derrière le bloc)
    
      // on récupère nos trois axes relatifs à notre longueur/hauteur/profondeur
    
      //noinspection UnnecessaryLocalVariable
      Axis depthAxis = faceAxis;
    
      Axis heightAxis = switch(faceAxis) {
         // le joueur mine à l'horizontal, la hauteur est forcément l'axe Y
         case X, Z -> Axis.Y;
       
         case Y -> {
            // le joueur mine le sol ou le ciel,
            // l'axe Y représente la profondeur (devant/derrière) donc
            // il faut prendre un autre axe à partir de la direction du joueur
          
            //   0°: +z
            //  90°: +x
            // 180°: -z
            // 270°: -x
            double xRot = playerPos.getYaw(); // -180 <= xRot < 180
          
            if(Math.signum(xRot) == -1.0) {
               xRot += 360;
            }
          
            // 0 <= xRot < 360
          
            // 90° pour chaque direction, à +/- 45° :
            // -45° ->  45°: +z
            //  45° -> 135°: +x
            // 135° -> 225°: -z
            // 225° -> 315°: -x
          
            // donc:
            //  45° -> 135° et 225° -> 315°: x
            // 315° ->  45° et 135° -> 225°: z
          
            if((xRot >= 45 && xRot < 135) || (xRot >= 225 && xRot < 315)) {
               yield Axis.X; // le corps du joueur est orienté vers l'axe X
            }
            else {
               yield Axis.Z; // le corps du joueur est orienté vers l'axe Z
            }
         }
      };
    
      Axis widthAxis = switch(faceAxis) {
         // la profondeur est l'axe X,
         // la hauteur est l'axe Y,
         // donc il ne reste plus que Z.
         case X -> Axis.Z;
       
         // la profondeur est l'axe Y,
         // la hauteur est l'axe X ou l'axe Z,
         // donc prenons le seul axe restant.
         case Y -> (heightAxis == Axis.X) ? Axis.Z : Axis.X;
       
         // la profondeur est l'axe Z,
         // la hauteur est l'axe Y,
         // donc il ne reste plus que X.
         case Z -> Axis.X;
      };
    
      // après les maths, le trou.
    
      final int startWidth = -(width / 2);
      final int endWidth = width + startWidth - 1;
    
      final int startHeight = -(height / 2);
      final int endHeight = height + startHeight - 1;
    
      final int startDepth = 0;
      final int endDepth = depth - 1;
    
      for(int w = startWidth; w <= endWidth; ++w) {
         for(int h = startHeight; h <= endHeight; ++h) {
            for(int d = startDepth; d <= endDepth; ++d) {
               int x = 0, y = 0, z = 0;
             
               switch(widthAxis) {
                  case X -> x = w;
                  case Y -> y = w;
                  case Z -> z = w;
               }
             
               switch(heightAxis) {
                  case X -> x = h;
                  case Y -> y = h;
                  case Z -> z = h;
               }
             
               switch(depthAxis) {
                  case X -> x = d;
                  case Y -> y = d;
                  case Z -> z = d;
               }
             
               Block relative = block.getRelative(x, y, z);
               if(relative.getType() != Material.BEDROCK) {
                  // enlève le bloc et drop ses loots,
                  // DROP UNIQUEMENT si `tool` est le bon outil
                  // (enlève toujours le bloc même si `tool` n'est pas le bon outil)
                  relative.breakNaturally(tool);
               }
            }
         }
      }
   }
 
   // mettre qqch dans l'item pour empêcher les joueurs de l'avoir en vanilla, typiquement une couleur,
   // mais dans ce cas il faut empêcher les joueurs de renommer notre outil
   private static boolean isMyHammer(@Nullable ItemStack tool) {
      ItemMeta meta;
    
      //noinspection ConstantConditions
      return tool != null && tool.getType() == Material.NETHERITE_PICKAXE && tool.hasItemMeta() && (meta = tool.getItemMeta()).hasDisplayName() && meta.getDisplayName().equals("Variegatus");
   }
 
   @NotNull // org.bukkit.Axis
   public static Axis getAxis(BlockFace face) {
      return switch(face) {
         case EAST, WEST -> Axis.X;
         case UP, DOWN, SELF -> Axis.Y;
         case NORTH, SOUTH -> Axis.Z;
         default -> throw new IllegalArgumentException("non-cartesian face: " + face.name());
      };
   }
}

Cordialement,
ShE3py