Résolu Destruction de cages (Java)

  • Auteur de la discussion Auteur de la discussion Kenda
  • Date de début Date de début

Kenda

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

Actuellement en train de faire un plugin de skywars, je cherche à faire un système de cages.
J'ai crée donc tout ce qu'il faut, mais mes cages ne se détruisent pas.
Pourtant, mon code à l'air de fonctionner :

Java:
public static void destroyCages() {
        for (Chunk chunk : Bukkit.getWorld("world").getLoadedChunks()) {
            for (BlockState bs : chunk.getTileEntities()) {
                if (bs.getType() == Material.GLASS) {
                    bs.setType(Material.AIR);
                }
            }
        }
    }

Pourquoi donc mes cages ne se détruisent pas ?
Merci :)
 
Bonsoir,

Les blocs de verre ne sont pas des tile entities, donc tu n'auras jamais bs.getType() == Material.GLASS pour tout bs appartenant à Chunk#getTileEntities().
Par contre a priori c'est ton plugin qui fait apparaître les cages, donc tu sais où ce qu'elles sont pour les détruire sans analyser toute la map non ? Surtout que là tu n'enlèves pas les cages dans les chunks déchargés.

Cordialement,
ShE3py
 
Bonsoir,

Les blocs de verre ne sont pas des tile entities, donc tu n'auras jamais bs.getType() == Material.GLASS pour tout bs appartenant à Chunk#getTileEntities().
Par contre a priori c'est ton plugin qui fait apparaître les cages, donc tu sais où ce qu'elles sont pour les détruire sans analyser toute la map non ? Surtout que là tu n'enlèves pas les cages dans les chunks déchargés.

Cordialement,
ShE3py

D'accord, pourtant sur une vidéo, il utilise se système et les blocs disparaissais :confused:
Enfin bref, et mes cages ne sont pas géré par mon plugin, mais ce sont des locations, car je fais un système de multimap sur le même monde, donc pour sa que je cherche à supprimer les cages uniquement dans les Chuck chargés.

Mais alors c'est quel moyen pour supprimer tout les blocs de verres dans les zones chargés ?
Merci :)
 
D'accord, pourtant sur une vidéo, il utilise se système et les blocs disparaissais :confused:
C'est possible de le faire si les blocs sont des tile entities, ou éventuellement dans une dimension parallèle.

Enfin bref, et mes cages ne sont pas géré par mon plugin, mais ce sont des locations, car je fais un système de multimap sur le même monde, donc pour sa que je cherche à supprimer les cages uniquement dans les Chuck chargés.
Comme dit, si tu sais où les cages se situent exactement, ou même dans une distance inconnue par-rapport à un point, c'est mieux de chercher depuis là que dans toute la map.

Mais alors c'est quel moyen pour supprimer tout les blocs de verres dans les zones chargés ?
Merci :)
À coup de quadruple boucle.
Java:
// com.google.common.collect.Sets,
// tu peux enlever l'annotation si tu n'es pas sur IntelliJ,
// c'est juste pour qu'il affiche un avertissement/une erreur
// si on tente de modifier notre ensemble qui est immuable
@Unmodifiable
private static final ImmutableSet<Material> GLASSES = Sets.immutableEnumSet(
   // merci Bukkit.
   Material.GLASS,
   Material.WHITE_STAINED_GLASS,
   Material.ORANGE_STAINED_GLASS,
   Material.MAGENTA_STAINED_GLASS,
   Material.LIGHT_BLUE_STAINED_GLASS,
   Material.YELLOW_STAINED_GLASS,
   Material.LIME_STAINED_GLASS,
   Material.PINK_STAINED_GLASS,
   Material.GRAY_STAINED_GLASS,
   Material.LIGHT_GRAY_STAINED_GLASS,
   Material.CYAN_STAINED_GLASS,
   Material.PURPLE_STAINED_GLASS,
   Material.BLUE_STAINED_GLASS,
   Material.BROWN_STAINED_GLASS,
   Material.GREEN_STAINED_GLASS,
   Material.RED_STAINED_GLASS,
   Material.TINTED_GLASS
);

public static void removeCages() {
   World world = Bukkit.getWorld("world");
 
   // le monde peut ne pas exister (`level-name` dans `server.properties`)
   if(world == null) {
      throw new UnsupportedOperationException("goodbye world!");
   }
 
   // exclusif (y < maxHeight)
   final int maxHeight = world.getMaxHeight();
 
   // inclusif (y >= minHeight), mettre `0` si < 1.17
   final int minHeight = world.getMinHeight();
 
   for(Chunk chunk : world.getLoadedChunks()) {
      // les chunks sont divisés en sections sur l'axe Y,
      // donc garder le même Y plus longtemps optimise
      // (en théorie) les caches du processeur, donc travaillons
      // nous aussi en Y
      for(int y = minHeight; y < maxHeight; ++y) {
         // les autres coordonnées ne changent rien
         for(int x = 0; x < 16; ++x) {
            for(int z = 0; z < 16; ++z) {
               final Block block = chunk.getBlock(x, y, z);
             
               if(GLASSES.contains(block.getType())) {
                  block.setType(Material.AIR);
               }
            }
         }
      }
   }
}
 
Dernière édition:
C'est possible de le faire si les blocs sont des tile entities, ou éventuellement dans une dimension parallèle.
Donc si les maps auraient été dans un autre monde (autre que world), sa aurais pu fonctionner ?


Comme dit, si tu sais où les cages se situent exactement, ou même dans une distance inconnue par-rapport à un point, c'est mieux de chercher depuis là que dans toute la map.
J'avais testé avec les vector, mais j'avais que 1 bloc qui pouvais être retiré.

À coup de quadruple boucle.
Java:
// com.google.common.collect.Sets,
// tu peux enlever l'annotation si tu n'es pas sur IntelliJ,
// c'est juste pour qu'il affiche un avertissement/une erreur
// si on tente de modifier notre liste qui est immuable
@Unmodifiable
private static final ImmutableSet<Material> GLASSES = Sets.immutableEnumSet(
// merci Bukkit.
Material.GLASS,
Material.WHITE_STAINED_GLASS,
Material.ORANGE_STAINED_GLASS,
Material.MAGENTA_STAINED_GLASS,
Material.LIGHT_BLUE_STAINED_GLASS,
Material.YELLOW_STAINED_GLASS,
Material.LIME_STAINED_GLASS,
Material.PINK_STAINED_GLASS,
Material.GRAY_STAINED_GLASS,
Material.LIGHT_GRAY_STAINED_GLASS,
Material.CYAN_STAINED_GLASS,
Material.PURPLE_STAINED_GLASS,
Material.BLUE_STAINED_GLASS,
Material.BROWN_STAINED_GLASS,
Material.GREEN_STAINED_GLASS,
Material.RED_STAINED_GLASS,
Material.TINTED_GLASS
);

public static void removeCages() {
World world = Bukkit.getWorld("world");

// le monde peut ne pas exister (`level-name` dans `server.properties`)
if(world == null) {
throw new UnsupportedOperationException("goodbye world!");
}

// exclusif (y < maxHeight)
final int maxHeight = world.getMaxHeight();

// inclusif (y >= minHeight), mettre `0` si < 1.17
final int minHeight = world.getMinHeight();

for(Chunk chunk : world.getLoadedChunks()) {
// les chunks sont divisés en sections sur l'axe Y,
// donc garder le même Y plus longtemps optimise
// (en théorie) les caches du processeur, donc travaillons
// nous aussi en Y
for(int y = minHeight; y < maxHeight; ++y) {
// les autres coordonnées ne changent rien
for(int x = 0; x < 16; ++x) {
for(int z = 0; z < 16; ++z) {
final Block block = chunk.getBlock(x, y, z);

if(GLASSES.contains(block.getType())) {
block.setType(Material.AIR);
}
}
}
}
}
}
Sa marche bien en effet, c'est vrai que c'est pratique, après en plus on peux config et sa prend pas toute la map.
Merci bien :)
 
Donc si les maps auraient été dans un autre monde (autre que world), sa aurais pu fonctionner ?
C'était du sarcasme ; ce n'est pas possible dans notre monde de faire une ligne de code qui enlève un bloc quelconque à partir de son tile entity puisque seul certains blocs en ont.

J'avais testé avec les vector, mais j'avais que 1 bloc qui pouvais être retiré.
Vecteur de ? C'est un objet mathématique qui peut représenter tout et n'importe quoi.

Je suppose que par cage tu entends des blocs de verre qui empêchent les joueurs de partir, mais j'ai envie de dire que si c'est toi qui pose les blocs de verre, tu sais donc où sont-elles, et dans le pire des cas tu sais où sont les joueurs, alors il suffit d'enlever le verre dans les chunks où sont les joueurs.
 
C'était du sarcasme ; ce n'est pas possible dans notre monde de faire une ligne de code qui enlève un bloc quelconque à partir de son tile entity puisque seul certains blocs en ont.


Vecteur de ? C'est un objet mathématique qui peut représenter tout et n'importe quoi.

Je suppose que par cage tu entends des blocs de verre qui empêchent les joueurs de partir, mais j'ai envie de dire que si c'est toi qui pose les blocs de verre, tu sais donc où sont-elles, et dans le pire des cas tu sais où sont les joueurs, alors il suffit d'enlever le verre dans les chunks où sont les joueurs.
En gros ajouter X à la location de la cage pour atterrir sur le bloc, enfin un système qui date de quelques années, mais c'est useless, plus facile avec ta méthode.