Jump to content

Recommended Posts

Posted (edited)

I want to create customs chest for example red, green, blue and yellow chest.

What do i need to start with?

I found these classes: BlockChest - ContainerChest - TileEntityChest - TileEntityChestRenderer - GuiChest

Do i need to create them all? Can i extend on them? Should i also create my own chesthandler?

I just finished my custom crafting table and i was wondering how to make custom chests. It seems to be a bit more complex then crafting table :-)

Edited by winnetrie
Posted

So i have tried myself and this is what i achieved so far:

-I can place a custom chest down (with texture)

-the chest can be opened and the gui works fine

-it appears that the chest is working fine too (for now). I can place items in and out and.

-If i brake the chest the items drop like it should

-2 chests do not connect visualy, but they are in fact connected

-the closing chest sound has a delay of 5-6 seconds for some reason (ennoying!)

 

What i did is:

-extended on BlockChest

  Reveal hidden contents

Extended on TileEntityChest:

  Reveal hidden contents

Extended on TileEntityChestRenderer:

  Reveal hidden contents

created a guichest class extending guicontainer:

  Reveal hidden contents

 

Posted

I have sorted out all problems i had above!

I have now perfectly working custom chests so far now ( i think)

I also added my own doublechest handler, i registered all the renders and the TE.

I had to add a blockstate file like this:

{
  "forge_marker": 1,
  "defaults": {
    "model": "tem:modchest",
    "textures": {
       "particle": "minecraft:blocks/planks_oak",
       "chest": "minecraft:entity/chest/normal"
    }
  },
  "variants": {
    "normal": [{}],
    "inventory": [{}],
    "facing=east":[{}],
    "facing=west":[{}],
    "facing=south":[{}],
    "facing=north":[{}]
  }
}

It was giving me blockstate errors about the facing variant before. So i added a "dummy" blockstate.

I also added a reference to the item model (wich is in the block model folder or else it can't find it), because i needed an item model ofc.

I added the texture for the item and the particle effect for the block.

 

I hoped for some help from this forum, but i found out myself after all. :-)

 

Posted

I think you have to set the render size in the tile Entity. You will have to figure the method name out yourself I am currently unable to look at the libraries.

Posted

If your double chest is rendered on one of the two blocks, (i.e. the other is invisible,)

Override TileEntity::getRenderBoundingBox to return appropriate size of the double chest.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

Thank you, the problem has been solved.

However i have another question.

I was wondering how i would make multiple chest types?

As far as i think to understand is the specialrenderer bounded to the tileentity.

Like this:

ClientRegistry.bindTileEntitySpecialRenderer(TileEntityModChest.class, new ModTERChest());

So does this means i need to create another tileentity and specialrenderer for each chest i make? For example in 5 other colors.

The chestblock creates the tileentity. So could i make another enum that defines the 5 colors, then get from the constructor the parameter for the color and then give a new property to the blockstate with the defined color. Then when the tileentity has to be created , check the blockstate color and create the tileentity for that color.

Is this how i should do? Or is there a better or more easy way?

Posted

One Tileentity is enough, as field in the TE can  the color. Probably you can comfigure one chest TE to express the double one as well. (with isConnected or whatever)

Do what you think is the best :)

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

I think i'm doing it wrong.

When 1 tileentity is enough is 1 block also enough? I tried to give a variable to the tileentity but it is always the same.

when i create the chest it looks like this:

chest = new BlockModChest("modchest", 0);
chest2 = new BlockModChest("modchest2", 1);

i give a number as argument.

in the BlockModChest.class the constructor looks like this:

    public static int CHEST_ID;

    public BlockModChest(String blockname, int blockID)
    {
        super(Material.WOOD);
        this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
        this.CHEST_ID = blockID;
        this.setCreativeTab(Tem.decortab);
        setUnlocalizedName(blockname);
        setRegistryName(blockname);
    }

the i create the tileentity like this:

@Override
    public TileEntity createNewTileEntity(World worldIn, int meta)
    {
    	
    	TileEntityModChest te = new TileEntityModChest(); 
    	te.TileEntityID = CHEST_ID;
    	
    	System.out.println("the block id is: "+ CHEST_ID);
    	System.out.println("the chest id is: "+ te.TileEntityID);
    	return te;
    	
    }

It turns out that the tileentity gets always the id from the last instance i created of BlockModChest

 

I made also this class where the textures are defined:

public class ModChestUtility {
	
	
	public static final ResourceLocation texture_sprucechest_single = new ResourceLocation("tem:textures/models/entity/chest/test_green_normal.png");
	public static final ResourceLocation texture_sprucechest_double = new ResourceLocation("tem:textures/models/entity/chest/test_green_double.png");
	public static final ResourceLocation texture_birchchest_single = new ResourceLocation("tem:textures/models/entity/chest/test_brown_normal.png");
	public static final ResourceLocation texture_birchchest_double = new ResourceLocation("tem:textures/models/entity/chest/test_brown_double.png");

    
	
	
	public static enum chestType{
		SPRUCE("sprucechest",0,texture_sprucechest_single, texture_sprucechest_double),
		BIRCH("birchchest",1,texture_birchchest_single, texture_birchchest_double),
		JUNGLE("junglechest",2,texture_sprucechest_single, texture_sprucechest_double),
		ACACIA("acaciachest",3,texture_sprucechest_single, texture_sprucechest_double),
		DARKOAK("darkoakchest",4,texture_sprucechest_single, texture_sprucechest_double);
		
		private String chestname;
		private int ID;
		private ResourceLocation SingleChest;
		private ResourceLocation DoubleChest;
		
		chestType(String name, int id, ResourceLocation resloc, ResourceLocation resloc2){
			this.chestname = name;
			this.ID = id;
			this.SingleChest = resloc;
			this.DoubleChest = resloc2;
			
		}
		public String getChestName(){
			return chestname;
		}
		public int getChestID(){
			return ID;
		}
		public ResourceLocation getSingleChestTexture(){
			return SingleChest;
		}
		public ResourceLocation getDoubleChestTexture(){
			return DoubleChest;
		}
	}
	
	
}

So in the TESR i get the texture like this:

this.bindTexture(ModChestUtility.chestType.values()[te.TileEntityID].getDoubleChestTexture());

the texture is applied properly but all chests have the same textures because of te.TileEntityID is always the same

Posted
  On 5/14/2017 at 9:42 AM, winnetrie said:

It turns out that the tileentity gets always the id from the last instance i created of BlockModChest

Expand  

That's because you're storing the block ID as a static field, which is the same for every instance of the class - you're overriding it for all instances each time you construct a new instance.

Posted (edited)
  On 5/14/2017 at 9:42 AM, winnetrie said:

When 1 tileentity is enough is 1 block also enough?

Expand  

Yes. You don't need several blocks.

About double chest:You need to detect adjacent chest placement on somewhere like Block#onNeighborChanged, and change field of both tileentities.

 

About types: you can access blockstate on tileentity. Just put the chest type as blockstate. Also you need to configure the corresponding ItemBlock to apply the type on the block placement as well.

EDIT: ninja'd

Edited by Abastro

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted
  On 5/14/2017 at 10:31 AM, Jay Avery said:

That's because you're storing the block ID as a static field, which is the same for every instance of the class - you're overriding it for all instances each time you construct a new instance.

Expand  

Oh right, my bad. It is working now.

 

I think i'm almost there now, just a few bugs.

 

My doublechest is working fine, but when i destroy the right side, it rendering doesn't change to singlechest.

While it is in fact a single chest it looks like a double chest.

When i destroy the left side first the right turns invisible.

 

So i guess something isn't quite right in the tesr:

@SideOnly(Side.CLIENT)
public class ModTERChest extends TileEntitySpecialRenderer<TileEntityModChest>
{
    private static final ResourceLocation TEXTURE_TRAPPED_DOUBLE = new ResourceLocation("minecraft:textures/entity/chest/trapped_double.png");
    private static final ResourceLocation TEXTURE_CHRISTMAS_DOUBLE = new ResourceLocation("minecraft:textures/entity/chest/christmas_double.png");
    private static final ResourceLocation TEXTURE_NORMAL_DOUBLE = new ResourceLocation("minecraft:textures/entity/chest/normal_double.png");
    private static final ResourceLocation TEXTURE_TRAPPED = new ResourceLocation("minecraft:textures/entity/chest/trapped.png");
    private static final ResourceLocation TEXTURE_CHRISTMAS = new ResourceLocation("minecraft:textures/entity/chest/christmas.png");
    private static final ResourceLocation TEXTURE_NORMAL = new ResourceLocation("tem:textures/models/entity/chest/ironchest.png");
    private final ModelChest simpleChest = new ModelChest();
    private final ModelChest largeChest = new ModelLargeChest();
    private boolean isChristmas;

    public ModTERChest()
    {
        Calendar calendar = Calendar.getInstance();

        if (calendar.get(2) + 1 == 12 && calendar.get(5) >= 24 && calendar.get(5) <= 26)
        {
            this.isChristmas = true;
        }
    }

    @Override
    public void renderTileEntityAt(TileEntityModChest te, double x, double y, double z, float partialTicks, int destroyStage)
    {
        GlStateManager.enableDepth();
        GlStateManager.depthFunc(515);
        GlStateManager.depthMask(true);
        int i;

        if (te.hasWorld())
        {
            Block block = te.getBlockType();
            i = te.getBlockMetadata();

            if (block instanceof BlockModChest && i == 0)
            {
                ((BlockModChest)block).checkForSurroundingChests(te.getWorld(), te.getPos(), te.getWorld().getBlockState(te.getPos()));
                i = te.getBlockMetadata();
            }

            te.checkForAdjacentChests();
        }
        else
        {
            i = 0;
        }

        if (te.adjacentChestZNeg == null && te.adjacentChestXNeg == null)
        {
            ModelChest modelchest;

            if (te.adjacentChestXPos == null && te.adjacentChestZPos == null)
            {
                modelchest = this.simpleChest;

                if (destroyStage >= 0)
                {
                    this.bindTexture(DESTROY_STAGES[destroyStage]);
                    GlStateManager.matrixMode(5890);
                    GlStateManager.pushMatrix();
                    GlStateManager.scale(4.0F, 4.0F, 1.0F);
                    GlStateManager.translate(0.0625F, 0.0625F, 0.0625F);
                    GlStateManager.matrixMode(5888);
                }
                else if (this.isChristmas)
                {
                    this.bindTexture(TEXTURE_CHRISTMAS);
                }
                
                else
                {
                    this.bindTexture(ModChestUtility.chestType.values()[te.TileEntityID].getSingleChestTexture());
                }
            }
            else
            {
                modelchest = this.largeChest;

                if (destroyStage >= 0)
                {
                    this.bindTexture(DESTROY_STAGES[destroyStage]);
                    GlStateManager.matrixMode(5890);
                    GlStateManager.pushMatrix();
                    GlStateManager.scale(8.0F, 4.0F, 1.0F);
                    GlStateManager.translate(0.0625F, 0.0625F, 0.0625F);
                    GlStateManager.matrixMode(5888);
                }
                else if (this.isChristmas)
                {
                    this.bindTexture(TEXTURE_CHRISTMAS_DOUBLE);
                }
                
                else
                {
                    this.bindTexture(ModChestUtility.chestType.values()[te.TileEntityID].getDoubleChestTexture());
                }
            }

            GlStateManager.pushMatrix();
            GlStateManager.enableRescaleNormal();

            if (destroyStage < 0)
            {
                GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
            }

            GlStateManager.translate((float)x, (float)y + 1.0F, (float)z + 1.0F);
            GlStateManager.scale(1.0F, -1.0F, -1.0F);
            GlStateManager.translate(0.5F, 0.5F, 0.5F);
            int j = 0;

            if (i == 2)
            {
                j = 180;
            }

            if (i == 3)
            {
                j = 0;
            }

            if (i == 4)
            {
                j = 90;
            }

            if (i == 5)
            {
                j = -90;
            }

            if (i == 2 && te.adjacentChestXPos != null)
            {
                GlStateManager.translate(1.0F, 0.0F, 0.0F);
            }

            if (i == 5 && te.adjacentChestZPos != null)
            {
                GlStateManager.translate(0.0F, 0.0F, -1.0F);
            }

            GlStateManager.rotate((float)j, 0.0F, 1.0F, 0.0F);
            GlStateManager.translate(-0.5F, -0.5F, -0.5F);
            float f = te.prevLidAngle + (te.lidAngle - te.prevLidAngle) * partialTicks;

            if (te.adjacentChestZNeg != null)
            {
                float f1 = te.adjacentChestZNeg.prevLidAngle + (te.adjacentChestZNeg.lidAngle - te.adjacentChestZNeg.prevLidAngle) * partialTicks;

                if (f1 > f)
                {
                    f = f1;
                }
            }

            if (te.adjacentChestXNeg != null)
            {
                float f2 = te.adjacentChestXNeg.prevLidAngle + (te.adjacentChestXNeg.lidAngle - te.adjacentChestXNeg.prevLidAngle) * partialTicks;

                if (f2 > f)
                {
                    f = f2;
                }
            }

            f = 1.0F - f;
            f = 1.0F - f * f * f;
            modelchest.chestLid.rotateAngleX = -(f * ((float)Math.PI / 2F));
            modelchest.renderAll();
            GlStateManager.disableRescaleNormal();
            GlStateManager.popMatrix();
            GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);

            if (destroyStage >= 0)
            {
                GlStateManager.matrixMode(5890);
                GlStateManager.popMatrix();
                GlStateManager.matrixMode(5888);
            }
        }
    }
}

I still need to delete some lines. I haven't done it yet.

Posted
  On 5/14/2017 at 10:49 AM, Abastro said:

Yes. You don't need several blocks.

About double chestYou need to detect adjacent chest placement on somewhere like Block#onNeighborChanged, and change field of both tileentities.

 

About types: you can access blockstate on tileentity. Just put the chest type as blockstate. Also you need to configure the corresponding ItemBlock to apply the type on the block placement as well.

Expand  

Do you mean i should add the chest type as a property to the blockstate? I had that idea before, but i'm not sure how to acces the enum from another class.

Posted (edited)
  On 5/14/2017 at 11:12 AM, winnetrie said:

i'm not sure how to acces the enum from another class.

Expand  

Get it from the blockstate, it should be straightforward.

About the rendering bug, do you detect whether the adjacent chest is removed?

Edited by Abastro

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

I mean how can i acces the enums from ModChestUtility.class within BlockModChest.class

Because when i try this:

public PropertyEnum TYPE = PropertyEnum.create("type", ModChestUtility.chestType.class);

It give me an error saying:

Bound mismatch: The generic method create(String, Class<T>) of type PropertyEnum<T> is not applicable for the arguments (String, Class<ModChestUtility.chestType>). The inferred type ModChestUtility.chestType is not a valid
 substitute for the bounded parameter <T extends Enum<T> & IStringSerializable>

 

Posted

Let the enum override IStringSerializable.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

Alright i changed my ModChestUtility. class to ChestTypeEnum and it looks now like this:

public enum ChestTypeEnum implements IStringSerializable{
	
	
	
		SPRUCE("sprucechest",0,new ResourceLocation("tem:textures/models/entity/chest/test_green_normal.png"), 
				new ResourceLocation("tem:textures/models/entity/chest/test_green_double.png")),
		BIRCH("birchchest",1,new ResourceLocation("tem:textures/models/entity/chest/test_brown_normal.png"), 
				new ResourceLocation("tem:textures/models/entity/chest/test_brown_double.png")),
		JUNGLE("junglechest",2,new ResourceLocation("tem:textures/models/entity/chest/test_brown_normal.png"), 
				new ResourceLocation("tem:textures/models/entity/chest/test_brown_double.png"));
		//ACACIA("acaciachest",3,texture_sprucechest_single, texture_sprucechest_double),
		//DARKOAK("darkoakchest",4,texture_sprucechest_single, texture_sprucechest_double);
		
		private final String chestname;
		private final int ID;
		private final ResourceLocation SingleChest;
		private final ResourceLocation DoubleChest;
		
		private ChestTypeEnum(String name, int id, ResourceLocation resloc, ResourceLocation resloc2){
			this.chestname = name;
			this.ID = id;
			this.SingleChest = resloc;
			this.DoubleChest = resloc2;
			
		}
		public String getChestName(){
			return chestname;
		}
		public int getChestID(){
			return ID;
		}
		public ResourceLocation getSingleChestTexture(){
			return SingleChest;
		}
		public ResourceLocation getDoubleChestTexture(){
			return DoubleChest;
		}
		@Override
		public String getName() {
			// TODO Auto-generated method stub
			return null;
		}	
}

and in my BlockModChest i added the blockstate:

  Reveal hidden contents

 

Posted (edited)

Errors are gone now. Still got that rendering issue now

I added screenshots to see what i mean.

 

1 picture represent a green doublechest where the left side has been destroyed. You can clearly see that it still renders as a double chest but the left side of the chest has gone. To prove it i builded a fence on that place.

I also checked the inventory, that has been changed to a single chest inventory. So that is good.

 

The other picture was a doublechest where i destroyed the right side. The left side stops rendering for a reason i don't know yet.

It is still accesseble and the inventory is also like it should be.

 

I think this is the last problem i have now. When i can fix the rendering problems, i would be happy.

 

2017-05-14_15.23.10.png

2017-05-14_15.23.34.png

Edited by winnetrie
Posted (edited)
  On 5/14/2017 at 11:19 AM, Abastro said:

Get it from the blockstate, it should be straightforward.

About the rendering bug, do you detect whether the adjacent chest is removed?

Expand  

How exactly do i detect this? Is there a method for it? I used the vanilla code and i didn't changed it that much.

I still can't find the problem.....

EDIT: I just found out when i reload the game (closing the current map and then restart it) the chest have the right render.

So somehow the rendering doesn't get updated when i destroy 1 side of the chest.

Edited by winnetrie
Posted
  On 5/14/2017 at 11:27 PM, winnetrie said:

How exactly do i detect this? Is there a method for it?

Expand  

Probably, override Block::onNeighborChanged? It has been several versions after I worked on tileentity, so my memory is not clear. But there should be similar method.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

I have overidden it:

@Override
    public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos)
    {
        super.neighborChanged(state, worldIn, pos, blockIn, fromPos);
        TileEntity tileentity = worldIn.getTileEntity(pos);

        if (tileentity instanceof TileEntityModChest)
        {
            tileentity.updateContainingBlockInfo();
        }
    }

and in the tileentity:

@Override
    public void updateContainingBlockInfo()
    {
        super.updateContainingBlockInfo();
        this.adjacentChestChecked = false;
        doubleChestHandler = null;
    }

I'm not sure if i need to change something. This is what vanilla have

Posted (edited)

You need to update the rendering, call World::markAndNotifyBlock with flag 3.(the flag is explained on World::setBlock)

Edited by Abastro
Typo

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

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.