Jump to content

Recommended Posts

Posted

So I've cloned vanilla hoppers to a new format (unique logic to the automation process - I've added 3 slots that determine the "filter" of allowed items so as to remove the need for redstone in sorting. I am calling it a "filter." Novel name, right?) and I am curious: considering all I've done is a simple cloning and Hoppers don't use traditional stand-alone renderers, what would be the simplest way to say... change the color? Is there some simple access to render-time and a hue modifier or something to that effect? I honestly don't feel that trying to port the rendering method(s) tucked away in the Block renderer to an ISBRH is worth it, so if there's not a superficial hack this thing is staying grey! I'm actually open to suggestions because all I need the modification for is to be able to visually discern which are hoppers and which are filters.

I'll need help, and I'll give help. Just ask, you know I will!

Posted

Just make a TileEntitySpecialRenderer implementing ISimpleBlockRenderingHandler and only use the renderWorldBlock() method. To render the block just call the renderBlockHopperMetadata() method in RenderBlocks. You can use the Tessellators instance to manipulate the colors it has a method to do so. Also make sure to only return true in renderWorldBlock() if you actually render something otherwise the game will crash. You might also have to bind the default block texture atlas first for the textures to work. You can use this line of code to do so:

Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);

 

Good Luck

PM's regarding modding questions should belong in the Modder Support sub-forum and won't be answered.

Posted

The BlockRenderer uses a predefined texture, the Texture Atlas which is basically a huge texture containing all block textures. It then uses the UV coordinates given by the registered IIcon to find the hoppers texture on the atlas. Since these are hard-coded into the RenderBlocks class you cant change them. The only method to change the texture would be to render it dynamically (every frame) and manually bind a texture. But then you could also render a model without using RenderBlocks.

PM's regarding modding questions should belong in the Modder Support sub-forum and won't be answered.

Posted

Well thats the thing is I'm more of a logic programmer and haven't played with much rendering - MC or otherwise - so advice here can save me literally hours! I thought coming into it using the simple handler wouldn't be so simple, but I may give that a shot.

I'll need help, and I'll give help. Just ask, you know I will!

Posted

The BlockRenderer uses a predefined texture, the Texture Atlas which is basically a huge texture containing all block textures. It then uses the UV coordinates given by the registered IIcon to find the hoppers texture on the atlas. Since these are hard-coded into the RenderBlocks class you cant change them. The only method to change the texture would be to render it dynamically (every frame) and manually bind a texture. But then you could also render a model without using RenderBlocks.

 

See, the first part of your reply is why I thought it would be more involved, like copying the code over and converting to tesselators or wahtever... and the second part is what i dont want to try! But yoi convinced me to try the ISBRH.

I'll need help, and I'll give help. Just ask, you know I will!

Posted

Okay, I have to play the noob here...

 

public class FilterRenderer extends TileEntitySpecialRenderer implements ISimpleBlockRenderingHandler
{

@Override
public void renderInventoryBlock(Block block, int metadata, int modelId,
		RenderBlocks renderer) {
}

@Override
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z,
		Block block, int modelId, RenderBlocks renderer) {		

	// i'm not sure what the last boolean is... 50/50 chance!
	Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
	return renderer.renderBlockHopperMetadata((BlockHopper)block, x, y, z, modelId, true);
}

@Override
public boolean shouldRender3DInInventory(int modelId) {
	return false;
}

@Override
public int getRenderId() {
	// ?
	return Block.getIdFromBlock(IShop.filter);
}

@Override
public void renderTileEntityAt(TileEntity p_147500_1_, double p_147500_2_,
		double p_147500_4_, double p_147500_6_, float p_147500_8_) {
	// it made me implement this.... what to do?
}

}

 

And I tried to register as such...

RenderingRegistry.registerBlockHandler(new FilterRenderer());

 

But how is it impelented? By the ID assignement? Or the render type in the Block class?

/**
     * The type of render function that is called for this block
     */
    public int getRenderType()
    {
        return 38;
    }

 

Here's the whole block class just in case...

 

package com.kotr.ishop.block;

import java.util.List;
import java.util.Random;

import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.BlockHopper;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.Facing;
import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;

import com.kotr.ishop.main.IShop;
import com.kotr.ishop.tile_entity.TileEntityFilter;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class BlockFilter extends BlockHopper
{
    private final Random field_149922_a = new Random();
    @SideOnly(Side.CLIENT)
    public IIcon field_149921_b;
    @SideOnly(Side.CLIENT)
    public IIcon field_149923_M;
    @SideOnly(Side.CLIENT)
    public IIcon field_149924_N;
    
    public BlockFilter()
    {
        super();
        this.setCreativeTab(CreativeTabs.tabRedstone);
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    }

    /**
     * Updates the blocks bounds based on its current state. Args: world, x, y, z
     */
    public void setBlockBoundsBasedOnState(IBlockAccess p_149719_1_, int p_149719_2_, int p_149719_3_, int p_149719_4_)
    {
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    }

    /**
     * Adds all intersecting collision boxes to a list. (Be sure to only add boxes to the list if they intersect the
     * mask.) Parameters: World, X, Y, Z, mask, list, colliding entity
     */
    public void addCollisionBoxesToList(World p_149743_1_, int p_149743_2_, int p_149743_3_, int p_149743_4_, AxisAlignedBB p_149743_5_, List p_149743_6_, Entity p_149743_7_)
    {
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.625F, 1.0F);
        super.addCollisionBoxesToList(p_149743_1_, p_149743_2_, p_149743_3_, p_149743_4_, p_149743_5_, p_149743_6_, p_149743_7_);
        float f = 0.125F;
        this.setBlockBounds(0.0F, 0.0F, 0.0F, f, 1.0F, 1.0F);
        super.addCollisionBoxesToList(p_149743_1_, p_149743_2_, p_149743_3_, p_149743_4_, p_149743_5_, p_149743_6_, p_149743_7_);
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, f);
        super.addCollisionBoxesToList(p_149743_1_, p_149743_2_, p_149743_3_, p_149743_4_, p_149743_5_, p_149743_6_, p_149743_7_);
        this.setBlockBounds(1.0F - f, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        super.addCollisionBoxesToList(p_149743_1_, p_149743_2_, p_149743_3_, p_149743_4_, p_149743_5_, p_149743_6_, p_149743_7_);
        this.setBlockBounds(0.0F, 0.0F, 1.0F - f, 1.0F, 1.0F, 1.0F);
        super.addCollisionBoxesToList(p_149743_1_, p_149743_2_, p_149743_3_, p_149743_4_, p_149743_5_, p_149743_6_, p_149743_7_);
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    }

    /**
     * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata
     */
    public int onBlockPlaced(World p_149660_1_, int p_149660_2_, int p_149660_3_, int p_149660_4_, int p_149660_5_, float p_149660_6_, float p_149660_7_, float p_149660_8_, int p_149660_9_)
    {
        int j1 = Facing.oppositeSide[p_149660_5_];

        if (j1 == 1)
        {
            j1 = 0;
        }

        return j1;
    }

    /**
     * Returns a new instance of a block's tile entity class. Called on placing the block.
     */
    public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_)
    {
        return new TileEntityFilter();
    }

    /**
     * Called when the block is placed in the world.
     */
    public void onBlockPlacedBy(World p_149689_1_, int p_149689_2_, int p_149689_3_, int p_149689_4_, EntityLivingBase p_149689_5_, ItemStack p_149689_6_)
    {
        super.onBlockPlacedBy(p_149689_1_, p_149689_2_, p_149689_3_, p_149689_4_, p_149689_5_, p_149689_6_);

        if (p_149689_6_.hasDisplayName())
        {
            TileEntityFilter TileEntityFilter = func_149920_e(p_149689_1_, p_149689_2_, p_149689_3_, p_149689_4_);
            TileEntityFilter.func_145886_a(p_149689_6_.getDisplayName());
        }
    }

    /**
     * Called whenever the block is added into the world. Args: world, x, y, z
     */
    public void onBlockAdded(World p_149726_1_, int p_149726_2_, int p_149726_3_, int p_149726_4_)
    {
        super.onBlockAdded(p_149726_1_, p_149726_2_, p_149726_3_, p_149726_4_);
        this.func_149919_e(p_149726_1_, p_149726_2_, p_149726_3_, p_149726_4_);
    }

    /**
     * Called upon block activation (right click on the block.)
     */
    public boolean onBlockActivated(World p_149727_1_, int p_149727_2_, int p_149727_3_, int p_149727_4_, EntityPlayer p_149727_5_, int p_149727_6_, float p_149727_7_, float p_149727_8_, float p_149727_9_)
    {
        if (p_149727_1_.isRemote)
        {
            return true;
        }
        else
        {
            TileEntityFilter TileEntityFilter = func_149920_e(p_149727_1_, p_149727_2_, p_149727_3_, p_149727_4_);

            if (TileEntityFilter != null)
            {
            	// display filter gui
                //p_149727_5_.func_146093_a(TileEntityFilter);
            }

            return true;
        }
    }

    /**
     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
     * their own) Args: x, y, z, neighbor Block
     */
    public void onNeighborBlockChange(World p_149695_1_, int p_149695_2_, int p_149695_3_, int p_149695_4_, Block p_149695_5_)
    {
        this.func_149919_e(p_149695_1_, p_149695_2_, p_149695_3_, p_149695_4_);
    }

    private void func_149919_e(World p_149919_1_, int p_149919_2_, int p_149919_3_, int p_149919_4_)
    {
        int l = p_149919_1_.getBlockMetadata(p_149919_2_, p_149919_3_, p_149919_4_);
        int i1 = getDirectionFromMetadata(l);
        boolean flag = !p_149919_1_.isBlockIndirectlyGettingPowered(p_149919_2_, p_149919_3_, p_149919_4_);
        boolean flag1 = func_149917_c(l);

        if (flag != flag1)
        {
            p_149919_1_.setBlockMetadataWithNotify(p_149919_2_, p_149919_3_, p_149919_4_, i1 | (flag ? 0 : , 4);
        }
    }

    public void breakBlock(World p_149749_1_, int p_149749_2_, int p_149749_3_, int p_149749_4_, Block p_149749_5_, int p_149749_6_)
    {
        TileEntityFilter TileEntityFilter = (TileEntityFilter)p_149749_1_.getTileEntity(p_149749_2_, p_149749_3_, p_149749_4_);

        if (TileEntityFilter != null)
        {
            for (int i1 = 0; i1 < TileEntityFilter.getSizeInventory(); ++i1)
            {
                ItemStack itemstack = TileEntityFilter.getStackInSlot(i1);

                if (itemstack != null)
                {
                    float f = this.field_149922_a.nextFloat() * 0.8F + 0.1F;
                    float f1 = this.field_149922_a.nextFloat() * 0.8F + 0.1F;
                    float f2 = this.field_149922_a.nextFloat() * 0.8F + 0.1F;

                    while (itemstack.stackSize > 0)
                    {
                        int j1 = this.field_149922_a.nextInt(21) + 10;

                        if (j1 > itemstack.stackSize)
                        {
                            j1 = itemstack.stackSize;
                        }

                        itemstack.stackSize -= j1;
                        EntityItem entityitem = new EntityItem(p_149749_1_, (double)((float)p_149749_2_ + f), (double)((float)p_149749_3_ + f1), (double)((float)p_149749_4_ + f2), new ItemStack(itemstack.getItem(), j1, itemstack.getItemDamage()));

                        if (itemstack.hasTagCompound())
                        {
                            entityitem.getEntityItem().setTagCompound((NBTTagCompound)itemstack.getTagCompound().copy());
                        }

                        float f3 = 0.05F;
                        entityitem.motionX = (double)((float)this.field_149922_a.nextGaussian() * f3);
                        entityitem.motionY = (double)((float)this.field_149922_a.nextGaussian() * f3 + 0.2F);
                        entityitem.motionZ = (double)((float)this.field_149922_a.nextGaussian() * f3);
                        p_149749_1_.spawnEntityInWorld(entityitem);
                    }
                }
            }

            p_149749_1_.func_147453_f(p_149749_2_, p_149749_3_, p_149749_4_, p_149749_5_);
        }

        super.breakBlock(p_149749_1_, p_149749_2_, p_149749_3_, p_149749_4_, p_149749_5_, p_149749_6_);
    }

    /**
     * The type of render function that is called for this block
     */
    public int getRenderType()
    {
        return 38;
    }

    /**
     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
     */
    public boolean renderAsNormalBlock()
    {
        return false;
    }

    /**
     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
     */
    public boolean isOpaqueCube()
    {
        return false;
    }

    /**
     * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
     * coordinates.  Args: blockAccess, x, y, z, side
     */
    @SideOnly(Side.CLIENT)
    public boolean shouldSideBeRendered(IBlockAccess p_149646_1_, int p_149646_2_, int p_149646_3_, int p_149646_4_, int p_149646_5_)
    {
        return true;
    }

    /**
     * Gets the block's texture. Args: side, meta
     */
    @SideOnly(Side.CLIENT)
    public IIcon getIcon(int p_149691_1_, int p_149691_2_)
    {
        return p_149691_1_ == 1 ? this.field_149923_M : this.field_149921_b;
    }

    public static int getDirectionFromMetadata(int p_149918_0_)
    {
        return p_149918_0_ & 7;
    }

    public static boolean func_149917_c(int p_149917_0_)
    {
        return (p_149917_0_ &  != 8;
    }

    /**
     * If this returns true, then comparators facing away from this block will use the value from
     * getComparatorInputOverride instead of the actual redstone signal strength.
     */
    public boolean hasComparatorInputOverride()
    {
        return true;
    }

    /**
     * If hasComparatorInputOverride returns true, the return value from this is used instead of the redstone signal
     * strength when this block inputs to a comparator.
     */
    public int getComparatorInputOverride(World p_149736_1_, int p_149736_2_, int p_149736_3_, int p_149736_4_, int p_149736_5_)
    {
        return Container.calcRedstoneFromInventory(func_149920_e(p_149736_1_, p_149736_2_, p_149736_3_, p_149736_4_));
    }

    @SideOnly(Side.CLIENT)
    public void registerBlockIcons(IIconRegister p_149651_1_)
    {
        this.field_149921_b = p_149651_1_.registerIcon("hopper_outside");
        this.field_149923_M = p_149651_1_.registerIcon("hopper_top");
        this.field_149924_N = p_149651_1_.registerIcon("hopper_inside");
    }

    @SideOnly(Side.CLIENT)
    public static IIcon getHopperIcon(String p_149916_0_)
    {
        return p_149916_0_.equals("hopper_outside") ? IShop.filter.field_149921_b : (p_149916_0_.equals("hopper_inside") ? IShop.filter.field_149924_N : null);
    }

    public static TileEntityFilter func_149920_e(IBlockAccess p_149920_0_, int p_149920_1_, int p_149920_2_, int p_149920_3_)
    {
        return (TileEntityFilter)p_149920_0_.getTileEntity(p_149920_1_, p_149920_2_, p_149920_3_);
    }

    /**
     * Gets the icon name of the ItemBlock corresponding to this block. Used by hoppers.
     */
    @SideOnly(Side.CLIENT)
    public String getItemIconName()
    {
        return "hopper";
    }
}

 

I'll need help, and I'll give help. Just ask, you know I will!

Posted

O.K., I found this on the wiki, and found out how to register properly, which did actually kick it to the rendering class I made.

 

	IShop.filter.renderID = RenderingRegistry.getNextAvailableRenderId();
	RenderingRegistry.registerBlockHandler(IShop.filter.renderID, new FilterRenderer());

 

But then, this line had issue in that the Boolean set to false would ignore the blocks directional metadata, and set to true would through a render error that it was already tessellating:

 

return renderer.renderBlockHopperMetadata((BlockHopper)block, x, y, z, modelId, true);

 

So I changed it to

@Override
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z,
		Block block, int modelId, RenderBlocks renderer) {		

	// i'm not sure what the last boolean is... 50/50 chance!
	Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
	return renderer.renderBlockHopper((BlockHopper)block, x, y, z);
}

 

...and BOOM! Now to get the color change per your suggestion...

I'll need help, and I'll give help. Just ask, you know I will!

Posted

And the final version of my renderer, with the rendering from metadata method copied and cleaned up a bit, so I can play with the color. Note: it only changes the color of the inside of the hopper (which is fine enough for what I wanted) but its calling an IIcon which could easily enough be overridden if someone else finds this and needs to do that.

 

@Override
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z,
		Block block, int modelId, RenderBlocks renderer) {		

	Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
	return this.renderBlockHopperMetadata(renderer, (BlockHopper)block, x, y, z, renderer.blockAccess.getBlockMetadata(x, y, z), false);
}

public boolean renderBlockHopperMetadata(RenderBlocks renderer, BlockHopper p_147799_1_, int p_147799_2_, int p_147799_3_, int p_147799_4_, int p_147799_5_, boolean p_147799_6_) {
	Tessellator tessellator = Tessellator.instance;
	int i1 = BlockHopper.getDirectionFromMetadata(p_147799_5_);
	double d0 = 0.625D;
	renderer.setRenderBounds(0.0D, d0, 0.0D, 1.0D, 1.0D, 1.0D);

	renderer.renderStandardBlock(p_147799_1_, p_147799_2_, p_147799_3_, p_147799_4_);

	float f1;

	if (!p_147799_6_) {
		tessellator.setBrightness(p_147799_1_.getMixedBrightnessForBlock(renderer.blockAccess, p_147799_2_, p_147799_3_, p_147799_4_));
		int j1 = p_147799_1_.colorMultiplier(renderer.blockAccess, p_147799_2_, p_147799_3_, p_147799_4_);
		float f = (float) (j1 >> 16 & 255) / 255.0F;
		f1 = (float) (j1 >> 8 & 255) / 255.0F;
		float f2 = (float) (j1 & 255) / 255.0F;

		if (EntityRenderer.anaglyphEnable) {
			float f3 = (f * 30.0F + f1 * 59.0F + f2 * 11.0F) / 100.0F;
			float f4 = (f * 30.0F + f1 * 70.0F) / 100.0F;
			float f5 = (f * 30.0F + f2 * 70.0F) / 100.0F;
			f = f3;
			f1 = f4;
			f2 = f5;
		}

	}

	IIcon iicon = BlockHopper.getHopperIcon("hopper_outside");
	IIcon iicon1 = BlockHopper.getHopperIcon("hopper_inside");
	f1 = 0.125F;

	tessellator.setColorOpaque(150, 25, 25);

	renderer.renderFaceXPos(p_147799_1_, (double) ((float) p_147799_2_ - 1.0F + f1), (double) p_147799_3_, (double) p_147799_4_, iicon);
	renderer.renderFaceXNeg(p_147799_1_, (double) ((float) p_147799_2_ + 1.0F - f1), (double) p_147799_3_, (double) p_147799_4_, iicon);
	renderer.renderFaceZPos(p_147799_1_, (double) p_147799_2_, (double) p_147799_3_, (double) ((float) p_147799_4_ - 1.0F + f1), iicon);
	renderer.renderFaceZNeg(p_147799_1_, (double) p_147799_2_, (double) p_147799_3_, (double) ((float) p_147799_4_ + 1.0F - f1), iicon);
	renderer.renderFaceYPos(p_147799_1_, (double) p_147799_2_, (double) ((float) p_147799_3_ - 1.0F) + d0, (double) p_147799_4_, iicon1);

	renderer.setOverrideBlockTexture(iicon);
	double d3 = 0.25D;
	double d4 = 0.25D;
	renderer.setRenderBounds(d3, d4, d3, 1.0D - d3, d0 - 0.002D, 1.0D - d3);

	renderer.renderStandardBlock(p_147799_1_, p_147799_2_, p_147799_3_, p_147799_4_);

	if (!p_147799_6_) {
		double d1 = 0.375D;
		double d2 = 0.25D;
		renderer.setOverrideBlockTexture(iicon);

		if (i1 == 0) {
			renderer.setRenderBounds(d1, 0.0D, d1, 1.0D - d1, 0.25D, 1.0D - d1);
			renderer.renderStandardBlock(p_147799_1_, p_147799_2_, p_147799_3_, p_147799_4_);
		}

		if (i1 == 2) {
			renderer.setRenderBounds(d1, d4, 0.0D, 1.0D - d1, d4 + d2, d3);
			renderer.renderStandardBlock(p_147799_1_, p_147799_2_, p_147799_3_, p_147799_4_);
		}

		if (i1 == 3) {
			renderer.setRenderBounds(d1, d4, 1.0D - d3, 1.0D - d1, d4 + d2, 1.0D);
			renderer.renderStandardBlock(p_147799_1_, p_147799_2_, p_147799_3_, p_147799_4_);
		}

		if (i1 == 4) {
			renderer.setRenderBounds(0.0D, d4, d1, d3, d4 + d2, 1.0D - d1);
			renderer.renderStandardBlock(p_147799_1_, p_147799_2_, p_147799_3_, p_147799_4_);
		}

		if (i1 == 5) {
			renderer.setRenderBounds(1.0D - d3, d4, d1, 1.0D, d4 + d2, 1.0D - d1);
			renderer.renderStandardBlock(p_147799_1_, p_147799_2_, p_147799_3_, p_147799_4_);
		}
	}

	renderer.clearOverrideBlockTexture();
	return true;
}

I'll need help, and I'll give help. Just ask, you know I will!

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.