Configuration Résolu Java : rotation tête de monstre

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 391
1
191
187
Bonjour à tous ! :D

Ca fait on bail une fois que je ne suis pas venu ! :D

Bon du coup je viens vers vous suite à pas mal de galère concernant le java. Je ne parviens pas à gérer les têtes de mob. Je voudrais faire 2 choses avec les têtes de skeleton et de wither skeleton. Le problème est sur le fait que une tête en elle même est un ItemStack, donc facile à équiper sur un joueur. Par contre, le problème apparait lorsqu'il faut définir ces têtes en tant que tête de mob. Non seulement je ne parviens pas à trouver la syntaxe pour le faire, mais ne plus ni sur internet ni sur les forums, je ne trouvent quasiment aucune information sur le sujet.

Ce que je souhaite gérer avec ces têtes, c'est d'une part équiper un joueur avec ces têtes de mob, mais d'autre part de faire flotter ces têtes et les faire tourner sur elle même. Mais c'est un autre sujet ça. Voici le peu de code que j'ai actuellement :

Code:
Player player = (Player) sender;


            if(args[0].equalsIgnoreCase("archer") && sender instanceof Player) {
                ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1, (byte)3);
                SkullMeta meta = (SkullMeta) skull.getItemMeta();
               
                skull.setItemMeta(meta);
                ItemStack head = player.getInventory().getHelmet();
            }

Voilà ! :D

Merci à vous pour votre aide ;)

AlexFatta
 

Detobel36

Créateur de plugins (PhoenixRebirth)
Support
17 Août 2012
10 531
24
2 247
347
28
Bruxelles - Belgique
www.phoenix-rebirth.fr
Salut,

J'ai rien compris...
Qu'est-ce qui ne fonctionne pas dans ton code ? Où as-tu besoin d'aide. Car la tu dis juste que tu n'y arrive pas de manière général mais concrètement où est-ce que tu bloques ?


Cordialement,
Detobel36
 

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 391
1
191
187
Bonjour !

Je souhaite utiliser les têtes de mobs (dans ce cas Skeleton et Wither Skeleton) afin d'une part équiper un joueur avec la tête d'un de ce ces mobs sur sa tête (en guise de "casque" donc), et d'autre part je souhaiterai faire léviter ces têtes dans le vide mais qu'elles puissent tourner sur elle même selon l'axe Y.

Pour le premier projet, j'ai enfin réussi à trouver la solution, au lieu d'essayer de se dépatouiller dans les syntaxes pour trouver la bonne etc... j'ai trouvé la liste de toutes les têtes des mobs : https://minecraft.gamepedia.com/Mob_head#Player_skins . J'ai donc utiliser le "MHF_Skeleton". Dans le code pour les curieux ça donne ceci :

Code:
ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1);
                SkullMeta meta = (SkullMeta) skull.getItemMeta();
                
                meta.setOwner("MHF_WSkeleton");
                skull.setItemMeta(meta);

Bref sur ce point rien de bien compliqué, c'est juste une simple attribution d'owner. Je suis allez cherché trop loin.



Pour le second projet, maintenant que je sais comment faire spawner des têtes avec le mobs que je souhaite, je voudrais donc faire léviter ces têtes et les faire tourner sur elles mêmes selon l'axe Y. Là où je coince en revanche, c'est pour les faire bouger. Faire spawner la tête en elle même c'est le premier point sur lequel je coince :
Code:
ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1);
            SkullMeta meta = (SkullMeta) skull.getItemMeta();
            
            meta.setOwner("MHF_WSkeleton");
            skull.setItemMeta(meta);
            
            Block b = player.getLocation().getBlock();
Il est donc évident que je dois maintenant faire apparaitre cette nouvelle tête. Comment je peux donc faire spawner cette tête à l'emplacement du block b ? "skull" étant du type ItemStack, je ne peux faire apparaitre qu'un bloc ou que un objet de type "Material" (Ex : "Material.AIR").
Ou alors, autre option, faire apparaitre ces têtes en tant qu'entités ce qui pourrait être plus simple, mais là encore, je ne sais pas du tout comment m'y prendre.

Pour la rotation, je me suis dit qu'un runnable pourrait remplacer la tête existante par une nouvelle tête ayant un pitch un peu supérieur au précédent de façon à ce que la tête tourne. Ca pourrait fonctionne selon toi ? Peux-tu me renseigner sur comment faire spawner les têtes d'une manière ou d'une autre (Block ou entity ?) ? :)

AlexFatta
 

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 391
1
191
187
Je pense que tu pourrais tout simplement gérer un Armor Stand invisible dont tu te débarasse après ^^
Bonjour !!

Bon j'ai fait un code qui me semble juste mais qui pourtant ne fonctionne pas. Je vous le met en dessous de façon à récupérer vos avis ;)

Code:
package fr.alexfatta.armorstand.manager;

import java.util.ArrayList;
import java.util.HashMap;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.ArmorStand;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;

import fr.alexfatta.armorstand.main;

public class ArmorStandManager {

    public static main instance;

    public static ArrayList<ArmorStand> stands = new ArrayList<>();
    public static int ID;
    private static HashMap<ArmorStand, Integer> standsList = new HashMap<>();

    public static ArmorStand Stand(Location loc) {

        ArmorStand stand = loc.getWorld().spawn(loc, ArmorStand.class);
        stand.setGravity(false);
        stand.setSmall(false);
        ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1);
        SkullMeta meta = (SkullMeta) skull.getItemMeta();

        meta.setOwner("MHF_WSkeleton");
        skull.setItemMeta(meta);
        stand.setHelmet(skull);
        stand.setVisible(true);
        stand.setCustomNameVisible(false);
        stands.add(stand);
        standsList.put(stand, stand.getEntityId());
        ID = stand.getEntityId();
        runnable(stand);
        return stand;
    }

    public static void runnable (ArmorStand stand) {
        Bukkit.getScheduler().scheduleSyncRepeatingTask(instance, new Runnable() {

            @Override
            public void run() {

                /*
                 * 1- Prendre position actuelle de l'as
                 * 2- calculer la nouvelle position de l'as
                 * 3- effacer l'ancien as
                 * 4- Placer le nouvel as
                 */
                
                float pitch = stand.getLocation().getPitch() + 1;
                stand.getLocation().setPitch(pitch);
                Location toLocate = new Location(stand.getWorld(), stand.getLocation().getX(), stand.getLocation().getY(),
                        stand.getLocation().getZ(), stand.getLocation().getYaw(), pitch);
                
                removeArmorStand();
                ArmorStand stand2 = toLocate.getWorld().spawn(toLocate, ArmorStand.class);
                stand2.setGravity(false);
                stand2.setSmall(false);
                ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1);
                SkullMeta meta = (SkullMeta) skull.getItemMeta();

                meta.setOwner("MHF_WSkeleton");
                skull.setItemMeta(meta);
                stand2.setHelmet(skull);
                stand2.setVisible(true);
                stand2.setCustomNameVisible(false);
                stands.add(stand2);
                standsList.put(stand2, stand2.getEntityId());
                
            }
        }, 20, 20);
    }
    
    public static void removeArmorStand (){
        for(World world : Bukkit.getServer().getWorlds()){
            for(org.bukkit.entity.Entity entity : world.getEntities()){
                if (entity instanceof ArmorStand) {
                    if(ArmorStandManager.stands.contains(entity) && standsList.containsKey(entity) && standsList.containsValue(entity.getEntityId())){
                        try {
                            entity.remove();
                            ArmorStandManager.stands.remove(entity);
                            standsList.remove(entity, entity.getEntityId());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    public static HashMap<ArmorStand, Integer> getStandsList() {
        return standsList;
    }

    public static void setStandsList(HashMap<ArmorStand, Integer> standsList) {
        ArmorStandManager.standsList = standsList;
    }



}
Voilà ! :D J'ai donc suivi la piste de l'armorstand mais il n'effectue pas de rotation. Savez-vous d'où peut venir le problème ?

AlexFatta
 

Detobel36

Créateur de plugins (PhoenixRebirth)
Support
17 Août 2012
10 531
24
2 247
347
28
Bruxelles - Belgique
www.phoenix-rebirth.fr
Salut,

Je ne sais pas où est le problème mais y a vraiment moyen de simplifier ton code (et donc d'éviter de faire des erreurs).
Commence par mettre tous tes attributs en private. Ca n'a pas d’intérêt de pouvoir les modifier depuis une autre class... Surtout quand ils sont initialisé dès le début.
Dans ton "runnable" tu fais exactement la même chose que dans la fonction "Stand"... Pourquoi avoir copié/collé du code ? Quand on développe il n'y a normalement aucun copié/collé à faire, ...
Pourquoi avoir une liste "stands" et un hashmap "standsList" ? Tu rajoutes des éléments en même temps et supprime également en même temps. Tu sauvegarde la même information. Surtout que tu n'utilise jamais la value de ton hashmap, seulement les clef. En effet, quand tu sauvegarde l'objet entity tu sauvegarde également son EntityId, inutile de le mettre en plus dans une hashmap.

A quoi sert l'attribut ID ? Vu qu'a chaque fois que tu fais spawn un armor stand tu écrase cette valeur. Cela signifie qu'après avoir fait spawn 3 armors stand tu n'a aucune idée de ce qui se trouve dans ID, le premier, le second ?

Et du coup, wait...
stand.getLocation().setPitch(pitch);
Quel utilité ? Vu que tu va supprimer l'armor stand... Tu ne fais même pas un stand.getLocation().getPitch() puis-ce que tu récupères directement la valeur "pitch".

----------------------------------------------
Sinon pour ton problème, moi je téléporterais l'entité au lieu de la supprimer à chaque fois...

On aurait donc:
PHP:
package fr.alexfatta.armorstand.manager;

import java.util.ArrayList;
import java.util.HashMap;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.ArmorStand;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;

import fr.alexfatta.armorstand.main;

public class ArmorStandManager {

    private static main instance;

    private static ArrayList<ArmorStand> stands = new ArrayList<>();

    public static ArmorStand spawnNewArmorStand(Location loc) {
        ArmorStand stand = spawnArmorStand(loc);
        runnable(stand);
    }

    public static ArmorStand spawnArmorStand(Location loc) {
        ArmorStand stand = loc.getWorld().spawn(loc, ArmorStand.class);
        stand.setGravity(false);
        stand.setSmall(false);
        ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1);
        SkullMeta meta = (SkullMeta) skull.getItemMeta();
        meta.setOwner("MHF_WSkeleton");
        skull.setItemMeta(meta);
        stand.setHelmet(skull);
        stand.setVisible(true);
        stand.setCustomNameVisible(false);
        stands.add(stand);
        return stand;
    }

    public static void runnable (ArmorStand stand) {
        Bukkit.getScheduler().scheduleSyncRepeatingTask(instance, new Runnable() {

            @Override
            public void run() {
                Location newLocation = (Location) stand.getLocation().clone();
                float pitch = newLocation.getPitch() + 1;
                newLocation.setPitch(pitch);
                stand.teleport(newLocation);
            }
        }, 20L, 20L);
    }
   
    public static void removeArmorStand(){
        for(ArmorStand stand : stands) {
            stand.remove();
        }
        stands.clear();
    }

}
Attention: je n'ai pas testé le code et l'ai directement écrit dans un bête éditeur de texte. Il y a donc surement des erreurs ;)


Cordialement,
Detobel36
 

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 391
1
191
187
Bonsoir !

Merci Deto pour ta réponse si précise. Alors concernant tous les points que tu as cité, c'est vrai après mur réflexion que pas mal de choses sont illogiques xD

J'ai testé ton code, qui me semble absolument correct sauf que cela ne fonctionne pas. L'ArmorStand se place dans la direction dans laquelle je regarde mais c'est tout, il ne se passe rien ensuite. Je ne sais pas d'où cela peut venir. Voici ma commande qui place l'armorstand :

Code:
    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        if (label.equalsIgnoreCase("as") && sender instanceof Player) {
            Player player = (Player) sender;
            if (args.length == 1) {

                //Poser un ArmorStand
                if (args[0].equalsIgnoreCase("set")) {
                    Location loc = player.getLocation();
                    ArmorStandManager.spawnNewArmorStand(loc);
                    player.sendMessage(ChatColor.GREEN + "Tu as mis un ArmorStand ici !");
                }

Et mon Main :

Code:
package fr.alexfatta.armorstand;

import org.bukkit.plugin.java.JavaPlugin;

import fr.alexfatta.armorstand.command.Commands;
import fr.alexfatta.armorstand.manager.ArmorStandManager;

public class main extends JavaPlugin {
    
    @Override
    public void onEnable() {
        ArmorStandManager.setInstance(this);
        getCommand("as").setExecutor(new Commands());
        System.out.println("ArmorStand enabled !");
    }
    
    @Override
    public void onDisable() {
        
    }

}

Des idées ? :/

AlexFatta