Jump to content

Recommended Posts

Posted

I am trying to render items in a blocks TESR.

This is what I tried:

package XFactHD.thermalreactors.client.render.tesr;

import XFactHD.thermalreactors.common.blocks.metal.TileEntityLeadChest;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelChest;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.ItemModelMesher;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.item.ItemStack;

import java.util.ArrayList;

public class TileEntityLeadChestRenderer extends TileEntitySpecialRenderer<TileEntityLeadChest>
{
    @Override
    public void renderTileEntityAt(TileEntityLeadChest te, double x, double y, double z, float partialTicks, int destroyStage)
    {
        ItemModelMesher mesher = Minecraft.getMinecraft().getRenderItem().getItemModelMesher();
        BlockModelRenderer blockModelRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelRenderer();

        GlStateManager.pushAttrib();
        GlStateManager.pushMatrix();
        GlStateManager.translate((float)x, (float)y, (float)z);

        int angle = 90;
        switch (te.getFacing())
        {
            case NORTH: angle *= 0; break;
            case EAST: angle *= 1; break;
            case SOUTH: angle *= 2; break;
            case WEST: angle *= 3;
        }

        GlStateManager.rotate(angle, 0, 1, 0);

        if (te.isOpen())
        {
            GlStateManager.translate((float)x, (float)y, (float)z);
            GlStateManager.translate(0, 5, 0);

            int offset = 5;

            ArrayList<ItemStack> teInv = te.getInventory();
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(0)); //The x, y and z values are for testing purposes as I
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(1)); // need to get the items rendering befor I can finetune
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(2)); //them
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(3));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(4));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(5));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(6));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(7));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get();
        }

        GlStateManager.popMatrix();
        GlStateManager.popAttrib();
    }

    private void renderItemAt(BlockModelRenderer blockModelRenderer, ItemModelMesher mesher, float x, float y, float z, ItemStack stack)
    {
        GlStateManager.pushMatrix();
        GlStateManager.translate(x, y, z);
        if (stack != null)
        {
            RenderHelper.enableStandardItemLighting();
            blockModelRenderer.renderModelBrightnessColor(mesher.getItemModel(stack), 1.0F, 1.0F, 1.0F, 1.0F);
            RenderHelper.disableStandardItemLighting();
        }
        GlStateManager.popMatrix();
    }
}

but this doesn't seem to work. Either the render method doesn't like to get an item with a missing model or I am probably overlooking something really simple.

Posted

I am trying to render items in a blocks TESR.

This is what I tried:

package XFactHD.thermalreactors.client.render.tesr;

import XFactHD.thermalreactors.common.blocks.metal.TileEntityLeadChest;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelChest;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.ItemModelMesher;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.item.ItemStack;

import java.util.ArrayList;

public class TileEntityLeadChestRenderer extends TileEntitySpecialRenderer<TileEntityLeadChest>
{
    @Override
    public void renderTileEntityAt(TileEntityLeadChest te, double x, double y, double z, float partialTicks, int destroyStage)
    {
        ItemModelMesher mesher = Minecraft.getMinecraft().getRenderItem().getItemModelMesher();
        BlockModelRenderer blockModelRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelRenderer();

        GlStateManager.pushAttrib();
        GlStateManager.pushMatrix();
        GlStateManager.translate((float)x, (float)y, (float)z);

        int angle = 90;
        switch (te.getFacing())
        {
            case NORTH: angle *= 0; break;
            case EAST: angle *= 1; break;
            case SOUTH: angle *= 2; break;
            case WEST: angle *= 3;
        }

        GlStateManager.rotate(angle, 0, 1, 0);

        if (te.isOpen())
        {
            GlStateManager.translate((float)x, (float)y, (float)z);
            GlStateManager.translate(0, 5, 0);

            int offset = 5;

            ArrayList<ItemStack> teInv = te.getInventory();
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(0)); //The x, y and z values are for testing purposes as I
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(1)); // need to get the items rendering befor I can finetune
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(2)); //them
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(3));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(4));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(5));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(6));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get(7));
            renderItemAt(blockModelRenderer, mesher, (float) x+0, (float) y+2, (float) z+0, teInv.get();
        }

        GlStateManager.popMatrix();
        GlStateManager.popAttrib();
    }

    private void renderItemAt(BlockModelRenderer blockModelRenderer, ItemModelMesher mesher, float x, float y, float z, ItemStack stack)
    {
        GlStateManager.pushMatrix();
        GlStateManager.translate(x, y, z);
        if (stack != null)
        {
            RenderHelper.enableStandardItemLighting();
            blockModelRenderer.renderModelBrightnessColor(mesher.getItemModel(stack), 1.0F, 1.0F, 1.0F, 1.0F);
            RenderHelper.disableStandardItemLighting();
        }
        GlStateManager.popMatrix();
    }
}

but this doesn't seem to work. Either the render method doesn't like to get an item with a missing model or I am probably overlooking something really simple.

Posted

This is what the chest looks like now:

This chest is made to contain radiation from fuel rods and raw uranium. If you put a fuel rod in there, it should be rendered upright (it has a max stacksize of 1) and if you insert up to 64 uranium pellets/chunks/whatever (with a max stack size of 64), they should be rendered as a pile with the height being proportional to the stack size. If I wouldn't use a TESR, how could I translate the item models to specific spots in the chest?

Posted

This is what the chest looks like now:

This chest is made to contain radiation from fuel rods and raw uranium. If you put a fuel rod in there, it should be rendered upright (it has a max stacksize of 1) and if you insert up to 64 uranium pellets/chunks/whatever (with a max stack size of 64), they should be rendered as a pile with the height being proportional to the stack size. If I wouldn't use a TESR, how could I translate the item models to specific spots in the chest?

Posted

How can I use IBakedModels in an IModel and what do I need to do in IModel#bake?

Posted

How can I use IBakedModels in an IModel and what do I need to do in IModel#bake?

Posted

Can I dynamically change the item models that are rendered in the chest when I use this method?

Posted

Can I dynamically change the item models that are rendered in the chest when I use this method?

Posted

I took a look at the OBJLoader and the ICustomModelLoader interface.

This is how far I got:

package XFactHD.thermalreactors.client.render.models;

import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ICustomModelLoader;
import net.minecraftforge.client.model.IModel;

import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

public enum  ModelLoaderLeadChest implements ICustomModelLoader
{
    INSTANCE;

    private IResourceManager manager;
    private final Map<ResourceLocation, IModel> cache = new HashMap<ResourceLocation, IModel>();

    @Override
    public boolean accepts(ResourceLocation modelLocation)
    {
        return modelLocation.getResourcePath().endsWith("_iRadioactive");
    }

    @Override
    public IModel loadModel(ResourceLocation modelLocation) throws Exception
    {
        ResourceLocation file = new ResourceLocation(modelLocation.getResourceDomain(), modelLocation.getResourcePath());
        if (!cache.containsKey(file))
        {
            IResource resource = null;
            try
            {
                resource = manager.getResource(file);
            }
            catch (FileNotFoundException e)
            {
                if (modelLocation.getResourcePath().startsWith("models/block/"))
                {
                    resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/item/" + file.getResourcePath().substring("models/block/".length())));
                }
                else if (modelLocation.getResourcePath().startsWith("models/item/"))
                {
                    resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/block/" + file.getResourcePath().substring("models/item/".length())));
                }
                else throw e;
            }
        }
        return cache.get(file);
    }

    @Override
    public void onResourceManagerReload(IResourceManager resourceManager)
    {
        this.manager = resourceManager;
        cache.clear();
    }

    @Override
    public String toString()
    {
        return "LeadChestLoader.INSTANCE";
    }
}

Now I've got some qestions:

[*]How do I get the IModel from an IResource? I took a look at the Vanilla Loader but I don't understand it at all.

[*]The chest can contain up to 9 different items, if the item has a stacksize higher than 1, it is even rendered multiple times. How would I go about caching that without filling up the memory with thousands of different models?

[*]What do I need to do in IModel#bake to create an IBakedModel?

Posted

I took a look at the OBJLoader and the ICustomModelLoader interface.

This is how far I got:

package XFactHD.thermalreactors.client.render.models;

import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ICustomModelLoader;
import net.minecraftforge.client.model.IModel;

import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

public enum  ModelLoaderLeadChest implements ICustomModelLoader
{
    INSTANCE;

    private IResourceManager manager;
    private final Map<ResourceLocation, IModel> cache = new HashMap<ResourceLocation, IModel>();

    @Override
    public boolean accepts(ResourceLocation modelLocation)
    {
        return modelLocation.getResourcePath().endsWith("_iRadioactive");
    }

    @Override
    public IModel loadModel(ResourceLocation modelLocation) throws Exception
    {
        ResourceLocation file = new ResourceLocation(modelLocation.getResourceDomain(), modelLocation.getResourcePath());
        if (!cache.containsKey(file))
        {
            IResource resource = null;
            try
            {
                resource = manager.getResource(file);
            }
            catch (FileNotFoundException e)
            {
                if (modelLocation.getResourcePath().startsWith("models/block/"))
                {
                    resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/item/" + file.getResourcePath().substring("models/block/".length())));
                }
                else if (modelLocation.getResourcePath().startsWith("models/item/"))
                {
                    resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/block/" + file.getResourcePath().substring("models/item/".length())));
                }
                else throw e;
            }
        }
        return cache.get(file);
    }

    @Override
    public void onResourceManagerReload(IResourceManager resourceManager)
    {
        this.manager = resourceManager;
        cache.clear();
    }

    @Override
    public String toString()
    {
        return "LeadChestLoader.INSTANCE";
    }
}

Now I've got some qestions:

[*]How do I get the IModel from an IResource? I took a look at the Vanilla Loader but I don't understand it at all.

[*]The chest can contain up to 9 different items, if the item has a stacksize higher than 1, it is even rendered multiple times. How would I go about caching that without filling up the memory with thousands of different models?

[*]What do I need to do in IModel#bake to create an IBakedModel?

Posted

#JavaQuestion

 

You have to cache it with "thousands of models". You can make it so your cache discards old models if it fills up, but if there are "thousands" of different versions of your block visible at a time then you need to have those "thousands" of models in memory.

 

As of now I am using WeakLinkedHashMap with maximum capacity (uses removeEldestEntry) which is basically LinkedHashMap that uses WeakValues (when value is not used entry is removed).

I had to do it myself since I couldn't find proper implementation.

 

Since you probably have more knowledge here - is there something in MC libs that allows such map that:

* Clears itself (values) when not used (values)

* Has max size

* Removes oldest entries when overloaded

 

I was looking into MapMaker and some of caching classes but didn't find anything to this extent.

 

In future I also want to improve mine with "waged values" since it (by logical analisys), when overloaded constantly will start recreating objects without caching them at all (since it is linked).

1.7.10 is no longer supported by forge, you are on your own.

Posted

#JavaQuestion

 

You have to cache it with "thousands of models". You can make it so your cache discards old models if it fills up, but if there are "thousands" of different versions of your block visible at a time then you need to have those "thousands" of models in memory.

 

As of now I am using WeakLinkedHashMap with maximum capacity (uses removeEldestEntry) which is basically LinkedHashMap that uses WeakValues (when value is not used entry is removed).

I had to do it myself since I couldn't find proper implementation.

 

Since you probably have more knowledge here - is there something in MC libs that allows such map that:

* Clears itself (values) when not used (values)

* Has max size

* Removes oldest entries when overloaded

 

I was looking into MapMaker and some of caching classes but didn't find anything to this extent.

 

In future I also want to improve mine with "waged values" since it (by logical analisys), when overloaded constantly will start recreating objects without caching them at all (since it is linked).

1.7.10 is no longer supported by forge, you are on your own.

Posted

You don't. You simply create a class implementing IModel and return it. Your model loader does not need to load anything from disk (resources).

What's the point of the custom ModelLoader then?

 

You have to cache it with "thousands of models". You can make it so your cache discards old models if it fills up, but if there are "thousands" of different versions of your block visible at a time then you need to have those "thousands" of models in memory.

What's the performance benefit of storing an obscene amount of models in comparison to rendering the block every frame?

 

Posted

You don't. You simply create a class implementing IModel and return it. Your model loader does not need to load anything from disk (resources).

What's the point of the custom ModelLoader then?

 

You have to cache it with "thousands of models". You can make it so your cache discards old models if it fills up, but if there are "thousands" of different versions of your block visible at a time then you need to have those "thousands" of models in memory.

What's the performance benefit of storing an obscene amount of models in comparison to rendering the block every frame?

 

Posted

If you are not rendering the block every frame, the block does not have to be rendered every frame (duh). Using some RAM does not reduce FPS.

Does this also apply if I have to regenerate the model(s) very often because the ItemStacks metadata or NBT data has changed and the ItemStack gotten from the extended block state is not equal to the reference stored in the Map as a key for the model?

Posted

If you are not rendering the block every frame, the block does not have to be rendered every frame (duh). Using some RAM does not reduce FPS.

Does this also apply if I have to regenerate the model(s) very often because the ItemStacks metadata or NBT data has changed and the ItemStack gotten from the extended block state is not equal to the reference stored in the Map as a key for the model?

Posted

I can't know beforehand what people (or myself) are doing to their ItemStacks (like making the ItemStack tick to simulate the half-life of an isotope) that could possibly be put into this chest.

 

EDIT: Also, I have no knowledge of the models/items that are to be put into my chest because they only need to implement an API interface to be able to put them into the chest.

Posted

I can't know beforehand what people (or myself) are doing to their ItemStacks (like making the ItemStack tick to simulate the half-life of an isotope) that could possibly be put into this chest.

 

EDIT: Also, I have no knowledge of the models/items that are to be put into my chest because they only need to implement an API interface to be able to put them into the chest.

Posted

I have to admit that I have exactly no idea how to implement what I want to do without the use of a TESR...

Posted

I have to admit that I have exactly no idea how to implement what I want to do without the use of a TESR...

Posted

I meant that I have no idea how to make the model work with what you told me above. I am understanding the reasoning of some of the parts of the puzzle now but overall I don't get how this is gonna work together. I have some questions again:

[*]The position of the item models depends on the rotation of the container and if I recall correctly (I am not at the computer right now), I do not have access to a block state in an IModel, how can I solve this?

[*]How is the TRSRTransformation supposed to work, this class just confuses me.

[*]Caching the models would mean saving the model in a Map with the ArrayList of stored items as a key, right?

Posted

I meant that I have no idea how to make the model work with what you told me above. I am understanding the reasoning of some of the parts of the puzzle now but overall I don't get how this is gonna work together. I have some questions again:

[*]The position of the item models depends on the rotation of the container and if I recall correctly (I am not at the computer right now), I do not have access to a block state in an IModel, how can I solve this?

[*]How is the TRSRTransformation supposed to work, this class just confuses me.

[*]Caching the models would mean saving the model in a Map with the ArrayList of stored items as a key, right?

Posted

I am asking the TE for an ArrayList that contains 9 ItemStacks, the TE's inventory.

How can I apply a TRSRTransformation in the IBakedModel?

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.