1.8 Minerais Custom, problème d'affichage



  • SOLUTION :

    Ajouter ça à la classe du minerai :

    @Override
    public EnumWorldBlockLayer getBlockLayer() {
    return EnumWorldBlockLayer.CUTOUT_MIPPED;
    }
    

    Enregistrer les textures comme ça :

    @SubscribeEvent
    public void registerOverlays(TextureStitchEvent.Pre e) {
    overlaysLocations.forEach(new BiConsumer<string, resourcelocation="">() {
    @Override
    public void accept(String srt, ResourceLocation location) {
    e.map.registerSprite(location);
    }
    });
    }
    

    #############################################################
    #############################################################

    Salut !

    J'ai implémenté un IModel pour pouvoir afficher des minerais custom qui ont différent background de pierre (géré par le metadata du bloc) avec un overlay du minerai (vanilla ou pas) (1 par instance du bloc).
    Le problème c'est que malgré tout les tutos que je me suis farcis, je comprend toujours pas tout.

    edit : petite précision :
    Il y a 24 types de pierre, coupé en 3*8 pour ne pas dépassé les 16 metadatas.
    Le nombre total d"instances (créée dynamiquement) du minerai custom est égal à 3 fois le nombre de minerais enregistrés (vanilla + mods)

    Le model ressemble à ça :

    public class OreBlockModel implements IModel {
    
    …
    
            public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function <resourcelocation, textureatlassprite="">bakedTextureGetter) {
    
    ModelResourceLocation stoneModelLocation = new ModelResourceLocation("minecraft:stone", null);
    IModel stoneModel = ModelLoaderRegistry.getModel(stoneModelLocation);
    IBakedModel stoneBakedModel = stoneModel.bake(stoneModel.getDefaultState(), format, bakedTextureGetter);
    Logger.info(stoneBakedModel.getTexture().getIconName()); // -> missing_texture
    
    IFlexibleBakedModel model = new IFlexibleBakedModel() {
    
    @Override
    public boolean isAmbientOcclusion() {
    return true;
    }
    
    @Override
    public boolean isGui3d() {
    return true;
    }
    
    @Override
    public boolean isBuiltInRenderer() {
    return false;
    }
    
    @Override
    public TextureAtlasSprite getTexture() {
    return bakedTextureGetter.apply(stoneModelLocation);
    }
    
    @Override
    public ItemCameraTransforms getItemCameraTransforms() {
    return ItemCameraTransforms.DEFAULT;
    }
    
    @Override
    public List <bakedquad>getFaceQuads(EnumFacing side) {
    return stoneBakedModel.getFaceQuads(side);
    }
    
    @Override
    public List <bakedquad>getGeneralQuads() {
    return stoneBakedModel.getGeneralQuads();
    }
    
    @Override
    public VertexFormat getFormat() {
    return format;
    }
    
    };
    
    return model;
    }
    }
    

    Avec un bloc vanilla ou pas, ça ne change rien, j'ai pas de texture (ou plutôt un jolie damier violet-noir), pourtant le model fonctionne et cette méthode bake() est appelé pour mes minerais, je le vois en jeu si je change isGui3D() par exemple.
    Je pense que le problème vient du bakedTextureGetter qui ne me renvois rien du tout pour une raison inconnue.

    Voici le reste du code, ce qui pourrai être lié du moins :

    public class OreModelLoader implements ICustomModelLoader {
    
       ...
    
    private IResourceManager resourceManager;
    
    @Override
    public void onResourceManagerReload(IResourceManager resourceManager) {
    this.resourceManager = resourceManager;
    }
    
    @Override
    public boolean accepts(ResourceLocation modelLocation) {
    return modelLocation.getResourceDomain().equals(MODID) && modelLocation.getResourcePath().contains(MODEL_NAME);
    }
    
    @Override
    public IModel loadModel(ResourceLocation modelLocation) {
    String modelName = modelLocation.getResourcePath();
    if (modelName.contains(MODEL_NAME)) {
    return new OreBlockModel(resourceManager, modelLocation);
    }
    throw new RuntimeException("A builtin model '" + modelName + "' is not defined.");
    }
    }
    

    Je ne veux pas utiliser ISmartBlockModel, parce qu'il me semble que le model est recalculé à chaque appel de rendu (en fonction du BlockState), c'est un peu overkill pour des minerais qui ne change pas d'état 😉
    Du coup j'ai quand même besoin de savoir la variante de pierre (metadata) et le minerais, pour choisir les bonnes textures, alors je passe ça dans la chaine du nom de model et je le récupère dans chaque instance d'IModel :

    public class UBOre extends Block {
    
    ...
    
    // le modelname est de la forme "modid:model_name_prefix.variant_de_pierre.oremodid:ore_name"
    // model_name_prefix est commun, c'est pour le "accept" dans OreModelLoader
    // oremodid et ore_name c'est pour trouver le bon overlay
    Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(this), i, new ModelResourceLocation(getModelName(i), "inventory"));
    
    ...
    
    }
    

    J'ai ça aussi dans mon client preinit :

    public void preInit(FMLPreInitializationEvent e) {
    super.preInit(e);
    
    StateMapperBase oresModelMapper = new StateMapperBase() {
    @Override
    protected ModelResourceLocation getModelResourceLocation(IBlockState state) {
                                   // Je suis pas sur ce que je doit mettre comme argument ici
                                   // j'hésite entre comme au dessus :
                                   // "modid:model_name_prefix.variant_de_pierre.oremodid:ore_name"
                                   // ou juste "modid:model_name_prefix"
    return new ModelResourceLocation(OreModelLoader.ORE_MODEL);
    }
    };
                   // CUSTOM_ORES = Les instances des blocs
    CUSTOM_ORES.forEach(new Consumer<customore>() {
    @Override
    public void accept(CustomOre ore) {
    ModelLoader.setCustomStateMapper(ore, oresModelMapper);
    }
    });
    ModelLoaderRegistry.registerLoader(new OreModelLoader());
    }
    

    Les topics/tutos qui m'ont aidé, au cas ou j'aurais loupé un truc :

    http://www.minecraftforge.net/forum/index.php?topic=29420.0
    http://www.minecraftforge.net/forum/index.php/topic,28714.0.html
    http://greyminecraftcoder.blogspot.com.au/2015/03/troubleshooting-block-and-item-rendering.html</customore></bakedquad></bakedquad></resourcelocation,></string,>


  • Modérateurs

    Pourquoi utiliser un IModel ? Ce serait plus simple de faire un block extends BlockOre.

    Envoyé de mon Nexus 4 en utilisant Tapatalk



  • Euh non, j'ai besoin de ce système parce que je créer des minerais dynamiquement


  • Modérateurs

    J'ai édité, j'ai fais un miss clic. Le tutoriel que je pensais n'a pas encore été rédiger.

    Envoyé de mon Nexus 4 en utilisant Tapatalk


  • Moddeurs confirmés Rédacteurs Administrateurs

    Utilise plutôt Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/stone"); pour avoir la texture de la stone.



  • Alors :
    Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("modid:blocks/custom");
    retourne correctement la TextureAtlasSprite donc ça ne vient pas des textures

    C'est vraiment bizarre, parce que les blocs utilise forcément le model retourné par bake() puisque quand je modifie isgui3d() ou isbuiltinrenderer(), je perçois le changement en jeu___Bon ça avance gentiment mais on est pas sortie de l'auberge ^^
    Mes minerais ont leur background de pierre qui s'affiche correctement - dans l'inventaire seulement mais c'est surement du à autre chose je m'en fous pour l'instant.

    public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function <resourcelocation, textureatlassprite="">bakedTextureGetter) {
        TextureMap textureMap = Minecraft.getMinecraft().getTextureMapBlocks();
        HashMap <resourcelocation, textureatlassprite="">txMap = new HashMap<>();
        Function <resourcelocation, textureatlassprite="">textureGetter;
        /*
         * Base stone and ore models
         */
        ModelResourceLocation stoneModelLocation = new ModelResourceLocation(MODID + ":" + stoneVariant);
        IModel stoneModel = ModelLoaderRegistry.getModel(stoneModelLocation);
        ModelResourceLocation oreModelLocation = new ModelResourceLocation(oreResourcesDomain + ":" + oreType);
        IModel oreModel = ModelLoaderRegistry.getModel(oreModelLocation);
        /*
         * Create the textures map
         */
        txMap.put(stoneModelLocation, textureMap.getAtlasSprite(MODID + ":blocks/" + stoneVariant));
        txMap.put(oreModelLocation, textureMap.getAtlasSprite(oreResourcesDomain + ":blocks/" + providedOverlays[2]));
        textureGetter = Functions.forMap(txMap);
        /*
         * Build the stone background
         */
        IBakedModel stoneBakedModel = stoneModel.bake(stoneModel.getDefaultState(), format, textureGetter);
        Builder b = new Builder(stoneBakedModel, textureGetter.apply(stoneModelLocation));
        /*
         * Add the ore overlay
         */
        IBakedModel oreBakedModel = oreModel.bake(oreModel.getDefaultState(), format, textureGetter);
        b.setTexture(textureGetter.apply(oreModelLocation));
        @SuppressWarnings("unchecked")
        List <bakedquad>oreBakedQuads = oreBakedModel.getGeneralQuads();
        for (BakedQuad bq : oreBakedQuads) {
            b.addGeneralQuad(bq);
        }
    
        return new IFlexibleBakedModel.Wrapper(b.makeBakedModel(), format);
    }
    

    Le nouveau problème, c'est que les overlays ne sont pas "enregistrés" dans minecraft, donc je dois trouver un moyen de le faire pour que le textureGetter me renvoie la bonne textures___Bump ! Quelqu'un à une idée pour enregistrer les textures d'overlays ?</bakedquad></resourcelocation,></resourcelocation,></resourcelocation,>


  • Moddeurs confirmés Rédacteurs Administrateurs

    Je fusionne tous tes messages, il faut éviter les boucles posts.

    Il me semble qu'il faut passer par l'event TextureSwitchEvent



  • Ok merci !
    Pour enregistrer une méthode pour un event c'est avec l'annotation EventRegister ou un truc comme ça ?


  • Moddeurs confirmés Rédacteurs Administrateurs



  • C'est bizarre, j'ai l'impression que les textures ne se charge toujours pas.
    Qu'est-ce que je fait de mal ?

    @SideOnly(Side.CLIENT)
    public final class TexturesRegistrationHandler {
    
    @SubscribeEvent
    public void registerOverlays(TextureStitchEvent.Pre e) {
    oresTexturizer.overlaysLocations.forEach(new BiConsumer<string, resourcelocation="">() {
    @Override
    public void accept(String srt, ResourceLocation location) {
    e.map.registerSprite(location);
    }
    });
    }
    
    }
    
    

    overlaysLocation est remplis comme ça :

    overlaysLocations.put("oreCoal_overlay", new ResourceLocation(MODID + ":blocks/" + "coal_overlay"));
    

    et récupéré comme ça :

    TextureMap textureMap = Minecraft.getMinecraft().getTextureMapBlocks();
    HashMap <resourcelocation, textureatlassprite="">txMap = new HashMap<>();
    Function <resourcelocation, textureatlassprite="">textureGetter;
    /*
    * Base stone and ore models
    */
    ModelResourceLocation stoneModelLocation = new ModelResourceLocation(MODID + ":" + stoneVariant);
    IModel stoneModel = ModelLoaderRegistry.getModel(stoneModelLocation);
    ModelResourceLocation oreModelLocation = new ModelResourceLocation(oreResourcesDomain + ":" + oreType);
    IModel oreModel = ModelLoaderRegistry.getModel(oreModelLocation);
    /*
    * Create the map with the useful textures
    */
    TextureAtlasSprite stoneTexture = textureMap.getAtlasSprite(MODID + ":blocks/" + stoneVariant);
    TextureAtlasSprite oreTexture = textureMap.getAtlasSprite(MODID + ":blocks/" + oreType + "_overlay");
    txMap.put(stoneModelLocation, stoneTexture);
    txMap.put(oreModelLocation, oreTexture);
    textureGetter = Functions.forMap(txMap);
    

    Et cette ligne :

    MinecraftForge.EVENT_BUS.register(new TexturesRegistrationHandler());
    

    Faut la mettre dans le preInit ou le Init ?</resourcelocation,></resourcelocation,></string,>


  • Moddeurs confirmés Rédacteurs Administrateurs

    Il faut utiliser e.map.setTextureEntry("nom interne au jeu", new UneClasseExtendsTextureAtlasSprite("modid:chemin de la texture à partir du dossier textures");
    Pour le nom interne au jeu je mets toujours le même nom que l'emplacement de la texture (modid:chemin de la texture à partir du dossier textures) pour ne pas compliquer les choses.
    Tu ne peux pas utiliser directement TextureAtlasSprite car le constructeur est protected, donc il faut faire une classe fille.



  • Comment je get mon overlay ? avec ça :

    Function <resourcelocation, textureatlassprite="">bakedTextureGetter
    

    ou comme ça :

    TextureMap textureMap = Minecraft.getMinecraft().getTextureMapBlocks();
    HashMap <resourcelocation, textureatlassprite="">txMap = new HashMap<>();
    Function <resourcelocation, textureatlassprite="">textureGetter;
    
    ModelResourceLocation oreModelLocation = new ModelResourceLocation(oreResourcesDomain + ":" + oreType);
    IModel oreModel = ModelLoaderRegistry.getModel(oreModelLocation);
    
    TextureAtlasSprite oreTexture = textureMap.getAtlasSprite(MODID + ":blocks/" + overlayName);
    txMap.put(oreModelLocation, oreTexture);
    textureGetter = Functions.forMap(txMap);
    

    EDIT : la première méthode ne fonctionne pas, la deuxième oui. J'ai enfin la texture de l'overlay, par contre elle s'applique pas sur le model, parce-que faut pas pousser non plus ^^ Et seulement l'item, pas le bloc dans le monde, lui il est violet et noir.
    Si quelqu'un vois un problème dans ce qui suit, le début marche, c'est la fin où ça se gâte, l'overlay n'a pas l'air d'être ajouté :

    public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function <resourcelocation, textureatlassprite="">bakedTextureGetter) {
    
       TextureMap textureMap = Minecraft.getMinecraft().getTextureMapBlocks();
       HashMap <resourcelocation, textureatlassprite="">txMap = new HashMap<>();
       Function <resourcelocation, textureatlassprite="">textureGetter;
       /*
        * Base stone and ore models
        */
       ModelResourceLocation stoneModelLocation = new ModelResourceLocation(MODID + ":" + stoneVariant);
       IModel stoneModel = ModelLoaderRegistry.getModel(stoneModelLocation);
       ModelResourceLocation oreModelLocation = new ModelResourceLocation(oreResourcesDomain + ":" + oreType);
       IModel oreModel = ModelLoaderRegistry.getModel(oreModelLocation);
       /*
        * Create the map with the useful textures
        */
       TextureAtlasSprite stoneTexture = textureMap.getAtlasSprite(MODID + ":blocks/" + stoneVariant);
       TextureAtlasSprite oreTexture = textureMap.getAtlasSprite(MODID + ":blocks/" + overlayName);
       //
       txMap.put(stoneModelLocation, stoneTexture);
       txMap.put(oreModelLocation, oreTexture);
       textureGetter = Functions.forMap(txMap);
       /*
        * Build the stone "background"
        */
       IBakedModel stoneBakedModel = stoneModel.bake(stoneModel.getDefaultState(), format, textureGetter);
       Builder b = new Builder(stoneBakedModel, textureGetter.apply(stoneModelLocation));
       /*
        * Add the ore overlay
        */
       IBakedModel oreBakedModel = oreModel.bake(oreModel.getDefaultState(), format, textureGetter);
       b.setTexture(textureGetter.apply(oreModelLocation));
       //
       List <bakedquad>oreBakedQuads = oreBakedModel.getGeneralQuads();
       for (BakedQuad bq : oreBakedQuads) {
       b.addGeneralQuad(bq);
       }
    
       return new IFlexibleBakedModel.Wrapper(b.makeBakedModel(), format);
    }
    ```</bakedquad></resourcelocation,></resourcelocation,></resourcelocation,></resourcelocation,></resourcelocation,></resourcelocation,>


  • Le problème c'est que oreBakedModel.getGeneralQuads(); retourne que dalle, pourtant, oreModel pointe vers un model de minerai de minecraft vailde !
    Quelqu'un peut il m'expliquer exactement ce qu'est un BakedQuad, parce-que c'est un peu abstrait pour moi …


  • Moddeurs confirmés Rédacteurs Administrateurs

    Honnêtement je ne peux pas t'aider x)
    Je n'ai jamais utilisé ces méthodes, la seule chose que j'ai utilisé c'est le ISmartBlockModel et je ne comprends pas grand chose non plus au système de rendu de la 1.8 😕



  • J'ai posté sur le forum anglais, on m'a envoyé sur ça :

    https://github.com/TheGreyGhost/MinecraftByExample/blob/master/src/main/java/minecraftbyexample/mbe15_item_smartitemmodel/ChessboardSmartItemModel.java

    Le problème c'est que dans son tuto c'est pour un plateau d'échec, c'est un peu hardcore pour un exemple je trouve.
    Je pense avoir compris à peu près en gros un BakedQuad c'est une texture + des coordonnées (relative au bloc), et un bloc de base est composé de 6 BakedQuad. J'ai ajouté 6 autres BakedQuad à mon model (les overlays) en suivant le tuto. Ils sont décalé de 0.001 vers l'extérieur par rapport au autres pour évité les "glitches".

    Mais ce qui m'embete vraiment c'est que j'arrive a ajouté un texture de terre par dessus mes blocs, mais pas un overlay, il doit avoir un problème avec la transparence.


Log in to reply