1.6.x Les entités de bloc (TileEntity)


  • Moddeurs confirmés Rédacteurs Administrateurs

    Vous savez actuellement créer des blocs, et avec plusieurs textures. Mais vos blocs sont toujours plutôt basique. Dans ce tutoriel, nous allons voir comment utiliser les TileEntity et les NBTtag.

    Introduction

    Vous vous demandez sûrement à quoi vont servir les TileEntity. Ils vont servir dans un premier temps à sauvegarder des variables dans le bloc, qui vont être indépendant l'un de l'autre. En gros, comme les coffres, les fours, etc …
    Les tileEntity peuvent aussi servir pour un faire un rendu special depuis un TileEntitySpecialRender, mais nous traiterons ça dans un autre tutoriel.
    Dans ce tutoriel, nous allons simplement voir comment enregistrer une variable, plus exactement une variable du type String qui sera le nom des 5 derniers joueurs qui ont fait un clic droit sur le bloc (comme sur le wiki de forge). Ce tutoriel est essentiel pour plusieurs futurs tutoriels (direction avec les metadatas, GUIs, systèmes de propriétaire (owner), et d'autres ...)

    Pour commencer, créez un bloc basique.

    Modification dans la classe du bloc

    Changez l'extends du bloc de Block à BlockContainer. Vous allez avoir une erreur dans le nom de la classe, faites "add unimplemented methods"
    Si votre bloc n'a pas de metadata, changez return null; par return new TileEntityTuto();
    Si votre bloc à des metadata, laissez cette fonction comme elle est et ajoutez :

    @Override
    public TileEntity createTileEntity(World world, int metadata)
    {
        if(metadata == 0)
        {
            return new TileEntityTutorial();
        }
        else if(metadata == 1)
        {
            return new TileEntityTutorial2();
        }
        else
        {
            return null;
        }
    }
    

    Avec ce code, mes deux premiers blocs ont un tileEntity, et les autres non. Vous pouvez aussi utiliser un switch.
    Important, si vous avez des metadatas avec tileEntity et d'autres non, il faut ajouter cette méthode :

    public boolean hasTileEntity(int metadata)
    {
        if(metadata == 0 || metadata == 1)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    

    Dans mon cas, je vais faire ce tutoriel par dessus un bloc avec des metadatas.

    Une autre fonction, qui va juste servir d'exemple dans ce tutoriel, elle n'est pas utile pour un tileEntity :

    public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int par6, float par7, float par8, float par9)
    {
        if(world.getBlockMetadata(x, y, z) == 0)
        {
            if(!world.isRemote)
            {
                TileEntityTutorial te = (TileEntityTutorial)world.getBlockTileEntity(x, y, z);
                te.addplayertolist(player.getEntityName());
                player.addChatMessage("Derniers utilisateurs : " + te.getPlayerList());
            }
            return true;
        }
        else
        {
            return false;
        }
    }
    

    Lorsqu'un joueur fait un clic droit sur le bloc, on vérifie que le metadata est 0 (je rappelle que j'ai créé mon tileEntity seulement sur le metadata 0) puis on vérifie que le monde n'est pas remote (donc cette fonction n'est que fait par le serveur ou le serveur intégré si vous êtes en solo), cela évite que la fonction soit exécuté deux fois, si un jour vous avez des bug d'affichage (quelque chose qui s'affiche en double), pensez à ajoutez cette fonction.
    Ensuite j’instancie le TileEntity (j’utilise "te" pour le nom, ce sont les initiales de TileEntity) , puis j'exécute une fonction que nous allons créer dans le tileEntity, et enfin j'affiche au joueur la liste des personnes qui ont fait un clic droit sur le bloc.
    Maintenant il faut créer la classe du TileEntity

    La classe du TileEntity

    package tutoriel.common;
    
    import net.minecraft.tileentity.TileEntity;
    
    public class TileEntityTutorial extends TileEntity
    {
    
    }
    

    Nous allons commencer par créer la variable qui va enregistrer le nom des joueurs :

    public String visiteur[] = new String[]{"visiteur0", "visiteur1", "visiteur2", "visiteur3", "visiteur4"};
    

    Très important, vos variables qui seront enregistrées dans les nbt doivent avoir une valeur par défaut, si vous me croyez pas, essayez avec public String visiteur[] = new String[5]; vous allez tomber sur un crash au moment du clic droit sur le bloc 😛
    Également, elles ne doivent pas être static, c'est pour ça qu'il faut toujours instancier le tileEntity, si vous les déclarez static, lorsque vous changerez la variable, ça sera fait sur tous les blocs de la map, ce qui détruit l’intérêt du TileEntity …

    Comme je l'ai expliqué au dessus, les TileEntity servent à enregistrer dans un nbt une variable, pour ça il y a deux méthodes :

    public void readFromNBT(NBTTagCompound nbtTag)
    {
        super.readFromNBT(nbtTag);
        for(int i = 0; i < 5; i++)
        {
            visiteur[i] = nbtTag.getString("visiteur" + i);
        }
    }
    
    public void writeToNBT(NBTTagCompound nbtTag)
    {
        super.writeToNBT(nbtTag);
        for(int i = 0; i < 5; i++)
        {
            nbtTag.setString("visiteur" + i, visiteur[i]);
        }
    }
    

    super.readFromNBT(nbtTag); et super.writeToNBT(nbtTag); servent à exécuter la fonction readFromNBT et writeToNBT qui se trouvent dans TileEntity.java, ne les enlevez pas sinon votre tile entity ne marchera pas (pour les curieux, il enregistre le nom + la position (x, y, z) du tileEntity, d'ailleurs pour le nom on reviendra dessus plus tard, il faut l'enregistrer dans la classe principale)
    Les boucles for servent juste à simplifier le code, cela revient à faire :

    visiteur[0] = nbtTag.getString("visiteur" + 1);
    visiteur[1] = nbtTag.getString("visiteur" + 2);
    visiteur[2] = nbtTag.getString("visiteur" + 3);
    visiteur[3] = nbtTag.getString("visiteur" + 4);
    visiteur[4] = nbtTag.getString("visiteur" + 5);
    

    Pour les get <quelque chose>(dans readFromNBT) :
    Votrevariable = nbtTag.get<type de variable>("le nom dans le nbt");
    Pour les set <quelque chose>(dans writeToNBT) :
    nbtTag.set<type de variable>("le nom dans le nbt", Votrevariable);

    Vous pouvez enregistrer des doubles, booleans, ints, shorts, bytes, etc
    Par exemple pour un boolean :

    maboolean = nbtTag.getBoolean("exemple");
    

    dans readFromNBT et

    nbtTag.setBoolean("exemple", maboolean);
    

    dans writeToNBT

    Maintenant que les variables sont enregistrées, nous allons créez une fonction qui va donner la liste des visiteurs :

    public String getPlayerList()
    {
        return visiteur[0] + ", " + visiteur[1] + ", " + visiteur[2] + ", " + visiteur[3] + ", " + visiteur[4] + ", ";
    }
    

    La fonction est du type String comme on veut obtenir un String. Normalement l'erreur que vous avez sur "te.getPlayerList()" dans votre bloc devrait avoir disparu.

    Dernière chose à faire, la fonction addplayertolist :

    public void addplayertolist(String playerName)
    {
        if(!visiteur[0].equals(playerName))
        {
            for(int i = 3; i >= 0; i–)
            {
                visiteur _= visiteur[i];
            }
            visiteur[0] = playerName;
        }
        worldObj.notifyBlockChange(xCoord, yCoord, zCoord, 2);
    }
    

    La condition sert à vérifier que la personne qui vient d'ouvrir le bloc n'est pas la personne qui a ouvert le bloc en dernier (pour éviter qu'il n'y est qu'une seule personne dans la liste si un joueur spam)
    Ensuite, une petite boucle for, qui revient à faire :

    visiteur[4] = visiteur[3];
    visiteur[3] = visiteur[2];
    visiteur[2] = visiteur[1];
    visiteur[1] = visiteur[0];
    

    Le visiteur[4] prend la valeur du visiteur[3], le 3 celui de 2, etc … En gros je décale la liste. Et pour finir, visiteur[0] prend la valeur du dernier joueur qui a fait un clic droit sur le bloc.
    La dernière fonction sert à update le bloc. Notez l’existence des variables worldObj, xCoord, yCoord et zCoord, elles pourront vous être très utile.

    Finition

    Un dernier code qui est très important, sans lui le tileEntity ne fonctionne pas, dans votre classe principale, dans la partie Init, ajoutez :

    //Registry
    GameRegistry.registerTileEntity(TileEntityTutorial.class, "TileEntityTutorial");
    

    TileEntityTutorial.class est la classe et "TileEntityTutorial" est le nom pour l'enregistrement du nbttag.

    Voila, c'est tout pour ce tutoriel, maintenant vous êtes prêt pour les GUIs et autres trucs plus complexes. 😉

    Pour ceux qui se sont perdus dans la classe du tileEntity, la voici en entière :

    package tutoriel.common;
    
    import net.minecraft.nbt.NBTTagCompound;
    import net.minecraft.tileentity.TileEntity;
    
    public class TileEntityTutorial extends TileEntity
    {
        public String visiteur[] = new String[]{"visiteur0", "visiteur1", "visiteur2", "visiteur3", "visiteur4"};
    
        public void readFromNBT(NBTTagCompound nbtTag)
        {
            super.readFromNBT(nbtTag);
            for(int i = 0; i < 5; i++)
            {
                visiteur[i] = nbtTag.getString("visiteur" + i);
            }
        }
    
        public void writeToNBT(NBTTagCompound nbtTag)
        {
            super.writeToNBT(nbtTag);
            for(int i = 0; i < 5; i++)
            {
                nbtTag.setString("visiteur" + i, visiteur[i]);
            }
        }
    
        public String getPlayerList()
        {
            return visiteur[0] + ", " + visiteur[1] + ", " + visiteur[2] + ", " + visiteur[3] + ", " + visiteur[4] + ", ";
        }
    
        public void addplayertolist(String playerName)
        {
            if(!visiteur[0].equals(playerName))
            {
                for(int i = 3; i >= 0; i–)
                {
                    visiteur[i + 1] = visiteur[i];
                }
                visiteur[0] = playerName;
            }
            worldObj.notifyBlockChange(xCoord, yCoord, zCoord, 2);
        }
    }
    

    Et sinon :
    Voir sur github + correction d'un crash sur les blocs qui n'ont pas de tileEntity



  • J'attend la suite avec impatience, j'ai toujours galéré a faire des TileEntity 🙂



  • Je sens que ce tutoriel va mettre utile ! 🙂

    Petite question par la même occasion, les TileEntity servent à faire des blocs conteneur comme les coffres, non ?


  • Administrateurs

    Aussi. Mais ils permettent de faire en sorte que le block ai une entité. 🙂


  • Moddeurs confirmés Rédacteurs Administrateurs

    @'Kanar':

    Je sens que ce tutoriel va mettre utile ! 🙂

    Petite question par la même occasion, les TileEntity servent à faire des blocs conteneur comme les coffres, non ?

    Oui, car le contenu du coffre est sauvegardé dans le nbt tag.


    Voila le tutoriel est terminé, je pense que je vais encore ajouter des détails demain, et il faut que je regarde encore la condition qui vérifie si le nom du joueur n'est pas le même n'a pas l'air de fonctionner, je sais pas pourquoi x)



  • Super tuto !


  • Moddeurs confirmés Rédacteurs Administrateurs

    Je vais voir pour mieux détaillé les nbt avec les différents type de variable (faire un exemple pour tout)
    Et je crois que je viens de trouver pourquoi la vérification du nom du joueur marche pas :
    if(!visiteur[0].equals(playerName));
    Ne me demandé pas pourquoi j'ai mis ce point virgule, mais il a rien à faire la, c'est surement pour ça que ça fail, je vais voir ça dès que je suis sur mon bon pc.


    En effet, c'était ça



  • Salut !

    J'ai un souci. Pour tester, j'ai recopier ton programme qui ressort les joueurs, mais au right-click ça crash. J'ai mis des System.out.println et j'ai remarqué que le code ne crash que lorsque j'appelle te.quelquechose(). Pourtant, j'ai vérifié, et hormis le nom des class, j'ai exactement le même code. Pourrais-tu m'aider ?

    Merci d'avance !

    PS : Voici le crash-log (La class du TileEntity est TileEntityPeripheral et celle du block est BlockComputerTerminal):

    –-- Minecraft Crash Report ----
    // I let you down. Sorry :(
    
    Time: 30/08/13 00:30
    Description: Unexpected error
    
    java.lang.NullPointerException
    at mods.virtualcraft.common.BlockComputerTerminal.onBlockActivated(BlockComputerTerminal.java:95)
    at net.minecraft.client.multiplayer.PlayerControllerMP.onPlayerRightClick(PlayerControllerMP.java:371)
    at net.minecraft.client.Minecraft.clickMouse(Minecraft.java:1378)
    at net.minecraft.client.Minecraft.runTick(Minecraft.java:1854)
    at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:898)
    at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:826)
    at net.minecraft.client.main.Main.main(Main.java:93)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
    at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
    
    A detailed walkthrough of the error, its code path and all known details is as follows:
    ---------------------------------------------------------------------------------------
    
    -- Head --
    Stacktrace:
    at mods.virtualcraft.common.BlockComputerTerminal.onBlockActivated(BlockComputerTerminal.java:95)
    at net.minecraft.client.multiplayer.PlayerControllerMP.onPlayerRightClick(PlayerControllerMP.java:371)
    at net.minecraft.client.Minecraft.clickMouse(Minecraft.java:1378)
    
    -- Affected level --
    Details:
    Level name: MpServer
    All players: 1 total; [EntityClientPlayerMP['Player192'/263, l='MpServer', x=32,49, y=65,62, z=244,24]]
    Chunk stats: MultiplayerChunkCache: 220
    Level seed: 0
    Level generator: ID 00 - default, ver 1\. Features enabled: false
    Level generator options:
    Level spawn location: World: (44,64,244), Chunk: (at 12,4,4 in 2,15; contains blocks 32,0,240 to 47,255,255), Region: (0,0; contains chunks 0,0 to 31,31, blocks 0,0,0 to 511,255,511)
    Level time: 6948 game time, 6948 day time
    Level dimension: 0
    Level storage version: 0x00000 - Unknown?
    Level weather: Rain time: 0 (now: false), thunder time: 0 (now: false)
    Level game mode: Game mode: creative (ID 1). Hardcore: false. Cheats: false
    Forced entities: 106 total; [EntityClientPlayerMP['Player192'/263, l='MpServer', x=32,49, y=65,62, z=244,24], EntitySheep['Sheep'/47, l='MpServer', x=-32,47, y=74,00, z=170,53], EntitySheep['Sheep'/51, l='MpServer', x=-32,88, y=72,00, z=184,13], EntitySheep['Sheep'/50, l='MpServer', x=-37,47, y=74,00, z=176,88], EntitySheep['Sheep'/49, l='MpServer', x=-40,50, y=74,00, z=169,69], EntitySheep['Sheep'/48, l='MpServer', x=-38,03, y=74,00, z=174,63], EntityCreeper['Creeper'/53, l='MpServer', x=-42,03, y=14,00, z=321,34], EntityCow['Cow'/68, l='MpServer', x=-27,50, y=63,00, z=302,28], EntityCow['Cow'/69, l='MpServer', x=-27,50, y=63,00, z=303,50], EntityCow['Cow'/70, l='MpServer', x=-29,47, y=66,00, z=289,38], EntityCow['Cow'/71, l='MpServer', x=-25,38, y=63,00, z=319,30], EntitySheep['Sheep'/67, l='MpServer', x=-18,66, y=73,00, z=173,19], EntityCreeper['Creeper'/72, l='MpServer', x=-23,94, y=19,00, z=324,13], EntityBat['Bat'/73, l='MpServer', x=-27,25, y=21,10, z=322,53], EntityCreeper['Creeper'/85, l='MpServer', x=-0,50, y=36,00, z=293,50], EntityCreeper['Creeper'/84, l='MpServer', x=-0,31, y=35,00, z=290,78], EntityCreeper['Creeper'/87, l='MpServer', x=-1,31, y=50,00, z=297,94], EntityBat['Bat'/86, l='MpServer', x=1,52, y=36,85, z=291,85], EntitySheep['Sheep'/81, l='MpServer', x=-1,41, y=83,00, z=224,83], EntitySheep['Sheep'/80, l='MpServer', x=-0,72, y=80,00, z=229,84], EntityCreeper['Creeper'/83, l='MpServer', x=-2,72, y=35,00, z=287,91], EntityCreeper['Creeper'/82, l='MpServer', x=-2,63, y=20,00, z=258,50], EntityZombie['Zombie'/89, l='MpServer', x=-13,34, y=21,00, z=321,91], EntitySkeleton['Skeleton'/91, l='MpServer', x=-0,91, y=25,00, z=324,44], EntitySkeleton['Skeleton'/90, l='MpServer', x=-4,84, y=24,00, z=324,22], EntitySkeleton['Skeleton'/102, l='MpServer', x=9,38, y=22,00, z=291,06], EntityCreeper['Creeper'/103, l='MpServer', x=15,67, y=21,28, z=302,42], EntitySquid['Squid'/100, l='MpServer', x=9,50, y=59,00, z=273,23], EntitySkeleton['Skeleton'/101, l='MpServer', x=11,56, y=14,00, z=290,63], EntitySheep['Sheep'/98, l='MpServer', x=7,44, y=78,00, z=182,56], EntitySheep['Sheep'/99, l='MpServer', x=4,84, y=77,00, z=215,47], EntityBat['Bat'/110, l='MpServer', x=6,34, y=45,10, z=313,75], EntityBat['Bat'/111, l='MpServer', x=13,33, y=55,00, z=319,67], EntitySkeleton['Skeleton'/108, l='MpServer', x=7,34, y=39,00, z=317,34], EntitySkeleton['Skeleton'/109, l='MpServer', x=0,22, y=38,00, z=317,69], EntityZombie['Zombie'/106, l='MpServer', x=0,59, y=27,00, z=313,84], EntitySkeleton['Skeleton'/107, l='MpServer', x=2,47, y=38,00, z=316,31], EntityCreeper['Creeper'/104, l='MpServer', x=0,06, y=35,00, z=289,63], EntitySquid['Squid'/105, l='MpServer', x=10,20, y=55,00, z=289,63], EntityZombie['Zombie'/118, l='MpServer', x=12,22, y=38,00, z=321,50], EntitySkeleton['Skeleton'/117, l='MpServer', x=8,47, y=39,00, z=321,28], EntitySkeleton['Skeleton'/116, l='MpServer', x=1,89, y=38,00, z=324,53], EntitySkeleton['Skeleton'/115, l='MpServer', x=0,44, y=38,00, z=322,16], EntitySkeleton['Skeleton'/112, l='MpServer', x=11,88, y=22,00, z=320,97], EntitySheep['Sheep'/127, l='MpServer', x=16,50, y=76,00, z=188,91], EntitySheep['Sheep'/126, l='MpServer', x=19,51, y=72,00, z=179,63], EntitySheep['Sheep'/125, l='MpServer', x=18,53, y=75,00, z=183,01], EntitySquid['Squid'/137, l='MpServer', x=16,53, y=55,04, z=274,48], EntitySkeleton['Skeleton'/136, l='MpServer', x=18,50, y=46,00, z=285,94], EntitySheep['Sheep'/139, l='MpServer', x=21,52, y=63,00, z=292,47], EntitySheep['Sheep'/138, l='MpServer', x=21,28, y=55,00, z=298,34], EntityCreeper['Creeper'/141, l='MpServer', x=28,44, y=15,00, z=307,88], EntitySheep['Sheep'/140, l='MpServer', x=31,34, y=59,00, z=296,56], EntitySkeleton['Skeleton'/143, l='MpServer', x=16,56, y=50,00, z=311,03], EntitySkeleton['Skeleton'/142, l='MpServer', x=26,50, y=39,00, z=314,31], EntityZombie['Zombie'/129, l='MpServer', x=17,53, y=14,00, z=237,97], EntitySheep['Sheep'/128, l='MpServer', x=19,72, y=77,00, z=218,22], EntitySquid['Squid'/131, l='MpServer', x=17,63, y=55,38, z=264,39], EntityZombie['Zombie'/130, l='MpServer', x=31,50, y=13,00, z=254,44], EntityZombie['Zombie'/133, l='MpServer', x=31,34, y=54,00, z=270,71], EntitySquid['Squid'/132, l='MpServer', x=19,21, y=55,02, z=271,08], EntitySkeleton['Skeleton'/135, l='MpServer', x=22,39, y=15,85, z=290,69], EntitySquid['Squid'/134, l='MpServer', x=19,22, y=55,40, z=264,81], EntitySkeleton['Skeleton'/144, l='MpServer', x=19,50, y=50,00, z=312,50], EntityZombie['Zombie'/146, l='MpServer', x=16,34, y=35,00, z=324,06], EntityCreeper['Creeper'/171, l='MpServer', x=40,00, y=14,03, z=305,91], EntitySheep['Sheep'/170, l='MpServer', x=34,75, y=63,00, z=292,88], EntityBat['Bat'/169, l='MpServer', x=41,59, y=55,10, z=301,25], EntityCreeper['Creeper'/168, l='MpServer', x=44,66, y=44,00, z=291,50], EntitySkeleton['Skeleton'/175, l='MpServer', x=63,25, y=22,00, z=272,84], EntitySkeleton['Skeleton'/174, l='MpServer', x=57,50, y=22,00, z=280,50], EntityBat['Bat'/173, l='MpServer', x=63,33, y=12,53, z=285,15], EntitySpider['Spider'/172, l='MpServer', x=57,75, y=67,00, z=175,72], EntityZombie['Zombie'/163, l='MpServer', x=36,16, y=15,00, z=292,59], EntityBat['Bat'/162, l='MpServer', x=35,75, y=13,10, z=292,38], EntitySheep['Sheep'/161, l='MpServer', x=44,34, y=63,00, z=285,91], EntityZombie['Zombie'/167, l='MpServer', x=34,30, y=37,81, z=299,37], EntityCreeper['Creeper'/166, l='MpServer', x=43,72, y=46,00, z=297,09], EntityBat['Bat'/165, l='MpServer', x=43,74, y=11,92, z=303,06], EntitySkeleton['Skeleton'/164, l='MpServer', x=37,09, y=12,00, z=290,50], EntityBat['Bat'/186, l='MpServer', x=69,25, y=18,10, z=223,75], EntityCreeper['Creeper'/187, l='MpServer', x=74,47, y=18,00, z=222,97], EntityZombie['Zombie'/190, l='MpServer', x=66,84, y=22,00, z=272,03], EntitySkeleton['Skeleton'/191, l='MpServer', x=72,70, y=11,00, z=319,70], EntityCreeper['Creeper'/188, l='MpServer', x=73,28, y=26,00, z=269,09], EntitySheep['Sheep'/189, l='MpServer', x=66,06, y=68,00, z=270,16], EntitySheep['Sheep'/178, l='MpServer', x=50,63, y=64,00, z=284,81], EntitySheep['Sheep'/179, l='MpServer', x=49,50, y=64,00, z=276,97], EntitySpider['Spider'/176, l='MpServer', x=48,97, y=44,00, z=284,28], EntityZombie['Zombie'/177, l='MpServer', x=54,44, y=42,00, z=286,31], EntitySheep['Sheep'/180, l='MpServer', x=57,44, y=67,00, z=317,66], EntityCreeper['Creeper'/205, l='MpServer', x=80,44, y=23,00, z=227,63], EntityZombie['Zombie'/204, l='MpServer', x=85,50, y=23,00, z=239,50], EntitySkeleton['Skeleton'/207, l='MpServer', x=89,69, y=11,00, z=314,31], EntityZombie['Zombie'/206, l='MpServer', x=88,88, y=12,00, z=315,06], EntityBat['Bat'/203, l='MpServer', x=86,88, y=16,70, z=220,10], EntityBat['Bat'/202, l='MpServer', x=94,53, y=16,10, z=219,25], EntitySheep['Sheep'/198, l='MpServer', x=64,35, y=69,00, z=321,16], EntityChicken['Chicken'/193, l='MpServer', x=73,41, y=68,00, z=314,47], EntityChicken['Chicken'/192, l='MpServer', x=74,16, y=67,00, z=312,16], EntityZombie['Zombie'/195, l='MpServer', x=72,69, y=19,00, z=322,56], EntityBat['Bat'/208, l='MpServer', x=76,36, y=21,92, z=323,00], EntityBat['Bat'/209, l='MpServer', x=93,39, y=17,12, z=318,31], EntityCreeper['Creeper'/236, l='MpServer', x=110,27, y=34,72, z=314,50], EntityBat['Bat'/235, l='MpServer', x=100,50, y=37,10, z=237,59], EntityBat['Bat'/234, l='MpServer', x=106,31, y=12,10, z=218,75]]
    Retry entities: 0 total; []
    Server brand: fml,forge
    Server type: Integrated singleplayer server
    Stacktrace:
    at net.minecraft.client.multiplayer.WorldClient.addWorldInfoToCrashReport(WorldClient.java:440)
    at net.minecraft.client.Minecraft.addGraphicsAndWorldToCrashReport(Minecraft.java:2298)
    at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:851)
    at net.minecraft.client.main.Main.main(Main.java:93)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
    at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
    
    – System Details --
    Details:
    Minecraft Version: 1.6.2
    Operating System: Windows 8 (amd64) version 6.2
    Java Version: 1.7.0_17, Oracle Corporation
    Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
    Memory: 763574080 bytes (728 MB) / 1038876672 bytes (990 MB) up to 1038876672 bytes (990 MB)
    JVM Flags: 3 total; -Xincgc -Xmx1024M -Xms1024M
    AABB Pool Size: 10447 (585032 bytes; 0 MB) allocated, 2 (112 bytes; 0 MB) used
    Suspicious classes: FML and Forge are installed
    IntCache: cache: 0, tcache: 0, allocated: 3, tallocated: 63
    FML: MCP v8.04 FML v6.2.19.789 Minecraft Forge 9.10.0.789 4 mods loaded, 4 mods active
    mcp{8.04} [Minecraft Coder Pack] (minecraft.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
    FML{6.2.19.789} [Forge Mod Loader] (coremods) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
    Forge{9.10.0.789} [Minecraft Forge] (coremods) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
    virtualcraft{0.1} [VirtualCraft] (bin) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
    Launched Version: 1.6
    LWJGL: 2.9.0
    OpenGL: Intel(R) HD Graphics 4000 GL version 4.0.0 - Build 9.17.10.2817, Intel
    Is Modded: Definitely; Client brand changed to 'fml,forge'
    Type: Client (map_client.txt)
    Resource Pack: Default
    Current Language: English (US)
    Profiler Position: N/A (disabled)
    Vec3 Pool Size: 3769 (211064 bytes; 0 MB) allocated, 17 (952 bytes; 0 MB) used
    

  • Moddeurs confirmés Rédacteurs Administrateurs

    Le tileEntity est bien enregistré ? La méthode pour créer le tileEntity est bien au dessus de celle du clic droit ?



  • Ouai, j'ai bien fait la GameRegistry dans la class principale.

    Voici le code de la TileEntity :

    :::

    package mods.virtualcraft.common;
    
    import net.minecraft.nbt.NBTTagCompound;
    import net.minecraft.tileentity.TileEntity;
    
    public class TileEntityPeripheral extends TileEntity
    {
    public String visiteur[] = new String[]{"visiteur0", "visiteur1", "visiteur2", "visiteur3", "visiteur4"};
    
    public void readFromNBT(NBTTagCompound nbtTag)
    {
    super.readFromNBT(nbtTag);
    for(int i = 0; i < 5; i++)
    {
    visiteur* = nbtTag.getString("visiteur" + i);
    }
    }
    
    public void writeToNBT(NBTTagCompound nbtTag)
    {
    super.writeToNBT(nbtTag);
    for(int i = 0; i < 5; i++)
    {
    nbtTag.setString("visiteur" + i, visiteur*);
    }
    }
    
    public String getPlayerList()
    {
    return visiteur[0] + ", " + visiteur[1] + ", " + visiteur[2] + ", " + visiteur[3] + ", " + visiteur[4] + ", ";
    }
    public boolean addPlayerToList(String playerName)
    {
    System.out.println("6");
    if(!visiteur[0].equals(playerName))
    {
    System.out.println("7");
    for(int i = 3; i >= 0; i–)
    {
    System.out.println("8 : "+i);
    visiteur _= visiteur*;
    }
    System.out.println("9");
    visiteur[0] = playerName;
    }
    System.out.println("10");
    worldObj.notifyBlockChange(xCoord, yCoord, zCoord, 2);
    return true;
    }
    }
    

    :::

    Voici le code du block :

    :::

    package mods.virtualcraft.common;
    //DUCK TALES FOREVER !
    import net.minecraft.block.BlockContainer;
    import net.minecraft.block.material.Material;
    import net.minecraft.client.renderer.texture.IconRegister;
    import net.minecraft.entity.player.EntityPlayer;
    import net.minecraft.tileentity.TileEntity;
    import net.minecraft.util.Icon;
    import net.minecraft.world.World;
    import cpw.mods.fml.relauncher.Side;
    import cpw.mods.fml.relauncher.SideOnly;
    
    public class BlockComputerTerminal extends BlockContainer {
    
    public BlockComputerTerminal(int par1, Material par2Material) {
    super(par1, par2Material);
    this.setCreativeTab(VirtualCraft.vctab);
    }
    
    @SideOnly(Side.CLIENT)
    private Icon[] icons;
    
    private String tplayer;
    
    @SideOnly(Side.CLIENT)
    public void registerIcons(IconRegister reg){
    icons = new Icon[4];
    
    icons[0] = reg.registerIcon("virtualcraft:Supercalculator3");
    icons[1] = reg.registerIcon("virtualcraft:ComputerTerminal");
    icons[2] = reg.registerIcon("virtualcraft:Supercalculator2");
    icons[3] = reg.registerIcon("virtualcraft:Supercalculator3");
    }
    @SideOnly(Side.CLIENT)
    public Icon getIcon(int par1, int par2)
    {
    switch(par2)
    {
    case 0:
    switch(par1)
    {
    case 0:
    return icons[3];
    case 1:
    return icons[2];
    default:
    return icons[1];
    }
    case 1:
    {
    switch(par1)
    {
    case 0:
    return icons[3];
    case 1:
    return icons[2];
    default:
    return icons[1];
    }
    }
    default:
    {
    System.out.println("Invalid metadata for " + this.getUnlocalizedName());
    return icons[0];
    }
    }
    }
    @Override
    public TileEntity createNewTileEntity(World world) {
    return null;
    }
    
    public boolean hasTileEntity(int metadata)
    {
    return true;
    }
    
    public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int par6, float par7, float par8, float par9)
    
    {
    System.out.println("1");
    if(world.getBlockMetadata(x, y, z) == 0)
    {
    System.out.println("2");
    if(!world.isRemote)
    {
    System.out.println("3");
    tplayer = player.getEntityName();
    System.out.println("4");
    TileEntityPeripheral te = (TileEntityPeripheral)world.getBlockTileEntity(x, y, z);
    System.out.println("5");
    //te.addPlayerToList(tplayer);
    System.out.println("11");
    player.addChatMessage("Derniers utilisateurs : " + te.getPlayerList());
    }
    return true;
    }
    else
    {
    return false;
    }
    
    }
    
    }
    
    

    :::_


  • Moddeurs confirmés

    La méthode pour créer le tileEntity est bien au dessus de celle du clic droit ?

    ça ne change rien vu que ce sont des méthode @Override donc c'est le positionnement dans les superclasse qui est important

    Sinon essaie de remplacer ça:

    
    }
    return true;
    
    

    par ça:

    
    return true;
    }
    else
    {
    return false
    }
    
    


  • Même résultat, crash à l'appel d'une fonction de la TileEntity.

    J'ai essayé de faire un @Override sur les fonctions dans la TE pour celle pour lequel ça pourrait être utile, mais aucune amélioration.


  • Moddeurs confirmés Rédacteurs Administrateurs

    Je viens de regarder ton code, en fait ton bloc n'a pas de tileEntity :

    @Override
    public TileEntity createNewTileEntity(World world) {
    return null;
    }
    

    Cette méthode doit bien être en null car c'est la méthode vanille de minecraft, mais tu n'a pas mit la méthode de forge (qui prend un compte les métadata) :

    @Override
    public TileEntity createTileEntity(World world, int metadata)
    {
    if(metadata == 0)
    {
    return new TileEntityTutorial();
    }
    else if(metadata == 1)
    {
    return new TileEntityTutorial2();
    }
    else
    {
    return null;
    }
    }
    

    Tu peux aussi utiliser un switch(metadata) vu que j'ai vue que tu les aimes bien ^^



  • Ah ok, merci, j'avais pas regardé le contenu de cette fonction, je pensais qu'elle ne servait que s'il y avait des metadatas.

    Effectivement, j'aime bien les switchs 🙂
    Ça fonctionne, merci !



  • bonjour je remonte le sujet car j'aimerais savoir plus le tileEntity mais pour la 1.7.2 j'ai 3 ou 4 erreur sur le code fourni que je n'arrive pas a resoudre, je sais qu'il y a eu quelque changement entre la 1.6 et 1.7, si possible robin que tu fasse un tuto plus précise sans utiliser les blocks metadata , sa m'aiderais énormément!. merci d'avance ^^


  • Moddeurs confirmés Rédacteurs Administrateurs

    Un nouveau tutoriel 1.7 est prévu.
    Les méthodes n'ont pas changés en 1.7, c'est toujours

    public TileEntity createTileEntity(World world, int metadata)
    {
    return new TileEntityPrivateChest();
    }
    

    et

    public boolean hasTileEntity(int metadata)
    {
    return true;
    }
    


  • çà doit etre tout bete , mais y a t'il moyen de détecter un click droit directemetn dans le tile entity , sans passer par la class du block ?


Log in to reply