Posted May 11, 20178 yr 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 May 21, 20178 yr by winnetrie Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 12, 20178 yr Author Need still some help. I'm not sure where to start. Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 12, 20178 yr Author 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 Spoiler public class BlockModChest extends BlockContainer { public static final PropertyDirection FACING = BlockHorizontal.FACING; protected static final AxisAlignedBB NORTH_CHEST_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0D, 0.9375D, 0.875D, 0.9375D); protected static final AxisAlignedBB SOUTH_CHEST_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.875D, 1.0D); protected static final AxisAlignedBB WEST_CHEST_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0625D, 0.9375D, 0.875D, 0.9375D); protected static final AxisAlignedBB EAST_CHEST_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 1.0D, 0.875D, 0.9375D); protected static final AxisAlignedBB NOT_CONNECTED_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.875D, 0.9375D); /** 0 : Normal chest, 1 : Trapped chest */ public final BlockChest.Type chestType; public BlockModChest(BlockChest.Type chestTypeIn) { super(Material.WOOD); this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH)); this.chestType = chestTypeIn; this.setCreativeTab(chestTypeIn == BlockChest.Type.TRAP ? CreativeTabs.REDSTONE : CreativeTabs.DECORATIONS); setUnlocalizedName("modchest"); setRegistryName("modchest"); } /** * Used to determine ambient occlusion and culling when rebuilding chunks for render */ public boolean isOpaqueCube(IBlockState state) { return false; } public boolean isFullCube(IBlockState state) { return false; } @Override @SideOnly(Side.CLIENT) public boolean hasCustomBreakingProgress(IBlockState state) { return true; } /** * The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only, * LIQUID for vanilla liquids, INVISIBLE to skip all rendering */ @Override public EnumBlockRenderType getRenderType(IBlockState state) { return EnumBlockRenderType.ENTITYBLOCK_ANIMATED; } @Override public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { return source.getBlockState(pos.north()).getBlock() == this ? NORTH_CHEST_AABB : (source.getBlockState(pos.south()).getBlock() == this ? SOUTH_CHEST_AABB : (source.getBlockState(pos.west()).getBlock() == this ? WEST_CHEST_AABB : (source.getBlockState(pos.east()).getBlock() == this ? EAST_CHEST_AABB : NOT_CONNECTED_AABB))); } /** * Called after the block is set in the Chunk data, but before the Tile Entity is set */ @Override public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state) { this.checkForSurroundingChests(worldIn, pos, state); for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL) { BlockPos blockpos = pos.offset(enumfacing); IBlockState iblockstate = worldIn.getBlockState(blockpos); if (iblockstate.getBlock() == this) { this.checkForSurroundingChests(worldIn, blockpos, iblockstate); } } } /** * Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the * IBlockstate */ @Override public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer) { return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing()); } /** * Called by ItemBlocks after a block is set in the world, to allow post-place logic */ @Override public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { EnumFacing enumfacing = EnumFacing.getHorizontal(MathHelper.floor((double)(placer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3).getOpposite(); state = state.withProperty(FACING, enumfacing); BlockPos blockpos = pos.north(); BlockPos blockpos1 = pos.south(); BlockPos blockpos2 = pos.west(); BlockPos blockpos3 = pos.east(); boolean flag = this == worldIn.getBlockState(blockpos).getBlock(); boolean flag1 = this == worldIn.getBlockState(blockpos1).getBlock(); boolean flag2 = this == worldIn.getBlockState(blockpos2).getBlock(); boolean flag3 = this == worldIn.getBlockState(blockpos3).getBlock(); if (!flag && !flag1 && !flag2 && !flag3) { worldIn.setBlockState(pos, state, 3); } else if (enumfacing.getAxis() != EnumFacing.Axis.X || !flag && !flag1) { if (enumfacing.getAxis() == EnumFacing.Axis.Z && (flag2 || flag3)) { if (flag2) { worldIn.setBlockState(blockpos2, state, 3); } else { worldIn.setBlockState(blockpos3, state, 3); } worldIn.setBlockState(pos, state, 3); } } else { if (flag) { worldIn.setBlockState(blockpos, state, 3); } else { worldIn.setBlockState(blockpos1, state, 3); } worldIn.setBlockState(pos, state, 3); } if (stack.hasDisplayName()) { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof TileEntityModChest) { ((TileEntityModChest)tileentity).setCustomName(stack.getDisplayName()); } } } public IBlockState checkForSurroundingChests(World worldIn, BlockPos pos, IBlockState state) { if (worldIn.isRemote) { return state; } else { IBlockState iblockstate = worldIn.getBlockState(pos.north()); IBlockState iblockstate1 = worldIn.getBlockState(pos.south()); IBlockState iblockstate2 = worldIn.getBlockState(pos.west()); IBlockState iblockstate3 = worldIn.getBlockState(pos.east()); EnumFacing enumfacing = (EnumFacing)state.getValue(FACING); if (iblockstate.getBlock() != this && iblockstate1.getBlock() != this) { boolean flag = iblockstate.isFullBlock(); boolean flag1 = iblockstate1.isFullBlock(); if (iblockstate2.getBlock() == this || iblockstate3.getBlock() == this) { BlockPos blockpos1 = iblockstate2.getBlock() == this ? pos.west() : pos.east(); IBlockState iblockstate7 = worldIn.getBlockState(blockpos1.north()); IBlockState iblockstate6 = worldIn.getBlockState(blockpos1.south()); enumfacing = EnumFacing.SOUTH; EnumFacing enumfacing2; if (iblockstate2.getBlock() == this) { enumfacing2 = (EnumFacing)iblockstate2.getValue(FACING); } else { enumfacing2 = (EnumFacing)iblockstate3.getValue(FACING); } if (enumfacing2 == EnumFacing.NORTH) { enumfacing = EnumFacing.NORTH; } if ((flag || iblockstate7.isFullBlock()) && !flag1 && !iblockstate6.isFullBlock()) { enumfacing = EnumFacing.SOUTH; } if ((flag1 || iblockstate6.isFullBlock()) && !flag && !iblockstate7.isFullBlock()) { enumfacing = EnumFacing.NORTH; } } } else { BlockPos blockpos = iblockstate.getBlock() == this ? pos.north() : pos.south(); IBlockState iblockstate4 = worldIn.getBlockState(blockpos.west()); IBlockState iblockstate5 = worldIn.getBlockState(blockpos.east()); enumfacing = EnumFacing.EAST; EnumFacing enumfacing1; if (iblockstate.getBlock() == this) { enumfacing1 = (EnumFacing)iblockstate.getValue(FACING); } else { enumfacing1 = (EnumFacing)iblockstate1.getValue(FACING); } if (enumfacing1 == EnumFacing.WEST) { enumfacing = EnumFacing.WEST; } if ((iblockstate2.isFullBlock() || iblockstate4.isFullBlock()) && !iblockstate3.isFullBlock() && !iblockstate5.isFullBlock()) { enumfacing = EnumFacing.EAST; } if ((iblockstate3.isFullBlock() || iblockstate5.isFullBlock()) && !iblockstate2.isFullBlock() && !iblockstate4.isFullBlock()) { enumfacing = EnumFacing.WEST; } } state = state.withProperty(FACING, enumfacing); worldIn.setBlockState(pos, state, 3); return state; } } public IBlockState correctFacing(World worldIn, BlockPos pos, IBlockState state) { EnumFacing enumfacing = null; for (EnumFacing enumfacing1 : EnumFacing.Plane.HORIZONTAL) { IBlockState iblockstate = worldIn.getBlockState(pos.offset(enumfacing1)); if (iblockstate.getBlock() == this) { return state; } if (iblockstate.isFullBlock()) { if (enumfacing != null) { enumfacing = null; break; } enumfacing = enumfacing1; } } if (enumfacing != null) { return state.withProperty(FACING, enumfacing.getOpposite()); } else { EnumFacing enumfacing2 = (EnumFacing)state.getValue(FACING); if (worldIn.getBlockState(pos.offset(enumfacing2)).isFullBlock()) { enumfacing2 = enumfacing2.getOpposite(); } if (worldIn.getBlockState(pos.offset(enumfacing2)).isFullBlock()) { enumfacing2 = enumfacing2.rotateY(); } if (worldIn.getBlockState(pos.offset(enumfacing2)).isFullBlock()) { enumfacing2 = enumfacing2.getOpposite(); } return state.withProperty(FACING, enumfacing2); } } @Override public boolean canPlaceBlockAt(World worldIn, BlockPos pos) { int i = 0; BlockPos blockpos = pos.west(); BlockPos blockpos1 = pos.east(); BlockPos blockpos2 = pos.north(); BlockPos blockpos3 = pos.south(); if (worldIn.getBlockState(blockpos).getBlock() == this) { if (this.isDoubleChest(worldIn, blockpos)) { return false; } ++i; } if (worldIn.getBlockState(blockpos1).getBlock() == this) { if (this.isDoubleChest(worldIn, blockpos1)) { return false; } ++i; } if (worldIn.getBlockState(blockpos2).getBlock() == this) { if (this.isDoubleChest(worldIn, blockpos2)) { return false; } ++i; } if (worldIn.getBlockState(blockpos3).getBlock() == this) { if (this.isDoubleChest(worldIn, blockpos3)) { return false; } ++i; } return i <= 1; } private boolean isDoubleChest(World worldIn, BlockPos pos) { if (worldIn.getBlockState(pos).getBlock() != this) { return false; } else { for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL) { if (worldIn.getBlockState(pos.offset(enumfacing)).getBlock() == this) { return true; } } return false; } } /** * Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor * change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid * block, etc. */ @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(); } } /** * Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated */ @Override public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof IInventory) { InventoryHelper.dropInventoryItems(worldIn, pos, (IInventory)tileentity); worldIn.updateComparatorOutputLevel(pos, this); } super.breakBlock(worldIn, pos, state); } /** * Called when the block is right clicked by a player. */ @Override public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { if (worldIn.isRemote) { return true; } else { ILockableContainer ilockablecontainer = this.getLockableContainer(worldIn, pos); if (ilockablecontainer != null) { playerIn.displayGUIChest(ilockablecontainer); if (this.chestType == BlockChest.Type.BASIC) { playerIn.addStat(StatList.CHEST_OPENED); } else if (this.chestType == BlockChest.Type.TRAP) { playerIn.addStat(StatList.TRAPPED_CHEST_TRIGGERED); } } return true; } } @Nullable public ILockableContainer getLockableContainer(World worldIn, BlockPos pos) { return this.getContainer(worldIn, pos, false); } @Nullable public ILockableContainer getContainer(World p_189418_1_, BlockPos p_189418_2_, boolean p_189418_3_) { TileEntity tileentity = p_189418_1_.getTileEntity(p_189418_2_); if (!(tileentity instanceof TileEntityModChest)) { return null; } else { ILockableContainer ilockablecontainer = (TileEntityModChest)tileentity; if (!p_189418_3_ && this.isBlocked(p_189418_1_, p_189418_2_)) { return null; } else { for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL) { BlockPos blockpos = p_189418_2_.offset(enumfacing); Block block = p_189418_1_.getBlockState(blockpos).getBlock(); if (block == this) { if (this.isBlocked(p_189418_1_, blockpos)) { return null; } TileEntity tileentity1 = p_189418_1_.getTileEntity(blockpos); if (tileentity1 instanceof TileEntityModChest) { if (enumfacing != EnumFacing.WEST && enumfacing != EnumFacing.NORTH) { ilockablecontainer = new InventoryLargeChest("container.chestDouble", ilockablecontainer, (TileEntityModChest)tileentity1); } else { ilockablecontainer = new InventoryLargeChest("container.chestDouble", (TileEntityModChest)tileentity1, ilockablecontainer); } } } } return ilockablecontainer; } } } /** * Returns a new instance of a block's tile entity class. Called on placing the block. */ @Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new TileEntityModChest(); } /** * Can this block provide power. Only wire currently seems to have this change based on its state. */ @Override public boolean canProvidePower(IBlockState state) { return this.chestType == BlockChest.Type.TRAP; } @Override public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) { if (!blockState.canProvidePower()) { return 0; } else { int i = 0; TileEntity tileentity = blockAccess.getTileEntity(pos); if (tileentity instanceof TileEntityModChest) { i = ((TileEntityModChest)tileentity).numPlayersUsing; } return MathHelper.clamp(i, 0, 15); } } @Override public int getStrongPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) { return side == EnumFacing.UP ? blockState.getWeakPower(blockAccess, pos, side) : 0; } private boolean isBlocked(World worldIn, BlockPos pos) { return this.isBelowSolidBlock(worldIn, pos) || this.isOcelotSittingOnChest(worldIn, pos); } private boolean isBelowSolidBlock(World worldIn, BlockPos pos) { return worldIn.getBlockState(pos.up()).isSideSolid(worldIn, pos.up(), EnumFacing.DOWN); } private boolean isOcelotSittingOnChest(World worldIn, BlockPos pos) { for (Entity entity : worldIn.getEntitiesWithinAABB(EntityOcelot.class, new AxisAlignedBB((double)pos.getX(), (double)(pos.getY() + 1), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 2), (double)(pos.getZ() + 1)))) { EntityOcelot entityocelot = (EntityOcelot)entity; if (entityocelot.isSitting()) { return true; } } return false; } @Override public boolean hasComparatorInputOverride(IBlockState state) { return true; } @Override public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos) { return Container.calcRedstoneFromInventory(this.getLockableContainer(worldIn, pos)); } /** * Convert the given metadata into a BlockState for this Block */ @Override public IBlockState getStateFromMeta(int meta) { EnumFacing enumfacing = EnumFacing.getFront(meta); if (enumfacing.getAxis() == EnumFacing.Axis.Y) { enumfacing = EnumFacing.NORTH; } return this.getDefaultState().withProperty(FACING, enumfacing); } /** * Convert the BlockState into the correct metadata value */ @Override public int getMetaFromState(IBlockState state) { return ((EnumFacing)state.getValue(FACING)).getIndex(); } /** * Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed * blockstate. */ @Override public IBlockState withRotation(IBlockState state, Rotation rot) { return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING))); } /** * Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed * blockstate. */ @Override public IBlockState withMirror(IBlockState state, Mirror mirrorIn) { return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING))); } @Override protected BlockStateContainer createBlockState() { return new BlockStateContainer(this, new IProperty[] {FACING}); } public static enum Type { BASIC, TRAP; } /* ======================================== FORGE START =====================================*/ @Override public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis) { return !isDoubleChest(world, pos) && super.rotateBlock(world, pos, axis); } } Extended on TileEntityChest: Spoiler public class TileEntityModChest extends TileEntityChest { private NonNullList<ItemStack> chestContents = NonNullList.<ItemStack>withSize(27, ItemStack.EMPTY); /** Determines if the check for adjacent chests has taken place. */ public boolean adjacentChestChecked; /** Contains the chest tile located adjacent to this one (if any) */ public TileEntityModChest adjacentChestZNeg; /** Contains the chest tile located adjacent to this one (if any) */ public TileEntityModChest adjacentChestXPos; /** Contains the chest tile located adjacent to this one (if any) */ public TileEntityModChest adjacentChestXNeg; /** Contains the chest tile located adjacent to this one (if any) */ public TileEntityModChest adjacentChestZPos; /** The current angle of the lid (between 0 and 1) */ public float lidAngle; /** The angle of the lid last tick */ public float prevLidAngle; /** The number of players currently using this chest */ public int numPlayersUsing; /** Server sync counter (once per 20 ticks) */ private int ticksSinceSync; private BlockChest.Type cachedChestType; public TileEntityModChest() { } public TileEntityModChest(BlockChest.Type typeIn) { this.cachedChestType = typeIn; } /** * Returns the number of slots in the inventory. */ @Override public int getSizeInventory() { return 27; } @Override public boolean isEmpty() { for (ItemStack itemstack : this.chestContents) { if (!itemstack.isEmpty()) { return false; } } return true; } /** * Get the name of this object. For players this returns their username */ @Override public String getName() { return this.hasCustomName() ? this.customName : "container.chest"; } public static void registerFixesChest(DataFixer fixer) { fixer.registerWalker(FixTypes.BLOCK_ENTITY, new ItemStackDataLists(TileEntityModChest.class, new String[] {"Items"})); } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); this.chestContents = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY); if (!this.checkLootAndRead(compound)) { ItemStackHelper.loadAllItems(compound, this.chestContents); } if (compound.hasKey("CustomName", 8)) { this.customName = compound.getString("CustomName"); } } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); if (!this.checkLootAndWrite(compound)) { ItemStackHelper.saveAllItems(compound, this.chestContents); } if (this.hasCustomName()) { compound.setString("CustomName", this.customName); } return compound; } /** * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. */ @Override public int getInventoryStackLimit() { return 64; } @Override public void updateContainingBlockInfo() { super.updateContainingBlockInfo(); this.adjacentChestChecked = false; doubleChestHandler = null; } @SuppressWarnings("incomplete-switch") private void setNeighbor(TileEntityModChest chestTe, EnumFacing side) { if (chestTe.isInvalid()) { this.adjacentChestChecked = false; } else if (this.adjacentChestChecked) { switch (side) { case NORTH: if (this.adjacentChestZNeg != chestTe) { this.adjacentChestChecked = false; } break; case SOUTH: if (this.adjacentChestZPos != chestTe) { this.adjacentChestChecked = false; } break; case EAST: if (this.adjacentChestXPos != chestTe) { this.adjacentChestChecked = false; } break; case WEST: if (this.adjacentChestXNeg != chestTe) { this.adjacentChestChecked = false; } } } } /** * Performs the check for adjacent chests to determine if this chest is double or not. */ @Override public void checkForAdjacentChests() { if (!this.adjacentChestChecked) { this.adjacentChestChecked = true; this.adjacentChestXNeg = this.getAdjacentChest(EnumFacing.WEST); this.adjacentChestXPos = this.getAdjacentChest(EnumFacing.EAST); this.adjacentChestZNeg = this.getAdjacentChest(EnumFacing.NORTH); this.adjacentChestZPos = this.getAdjacentChest(EnumFacing.SOUTH); } } @Override @Nullable protected TileEntityModChest getAdjacentChest(EnumFacing side) { BlockPos blockpos = this.pos.offset(side); if (this.isChestAt(blockpos)) { TileEntity tileentity = this.world.getTileEntity(blockpos); if (tileentity instanceof TileEntityModChest) { TileEntityModChest tileentitychest = (TileEntityModChest)tileentity; tileentitychest.setNeighbor(this, side.getOpposite()); return tileentitychest; } } return null; } private boolean isChestAt(BlockPos posIn) { if (this.world == null) { return false; } else { Block block = this.world.getBlockState(posIn).getBlock(); return block instanceof BlockChest && ((BlockChest)block).chestType == this.getChestType(); } } /** * Like the old updateEntity(), except more generic. */ @Override public void update() { this.checkForAdjacentChests(); int i = this.pos.getX(); int j = this.pos.getY(); int k = this.pos.getZ(); ++this.ticksSinceSync; if (!this.world.isRemote && this.numPlayersUsing != 0 && (this.ticksSinceSync + i + j + k) % 200 == 0) { this.numPlayersUsing = 0; float f = 5.0F; for (EntityPlayer entityplayer : this.world.getEntitiesWithinAABB(EntityPlayer.class, new AxisAlignedBB((double)((float)i - 5.0F), (double)((float)j - 5.0F), (double)((float)k - 5.0F), (double)((float)(i + 1) + 5.0F), (double)((float)(j + 1) + 5.0F), (double)((float)(k + 1) + 5.0F)))) { if (entityplayer.openContainer instanceof ContainerChest) { IInventory iinventory = ((ContainerChest)entityplayer.openContainer).getLowerChestInventory(); if (iinventory == this || iinventory instanceof InventoryLargeChest && ((InventoryLargeChest)iinventory).isPartOfLargeChest(this)) { ++this.numPlayersUsing; } } } } this.prevLidAngle = this.lidAngle; float f1 = 0.1F; if (this.numPlayersUsing > 0 && this.lidAngle == 0.0F && this.adjacentChestZNeg == null && this.adjacentChestXNeg == null) { double d1 = (double)i + 0.5D; double d2 = (double)k + 0.5D; if (this.adjacentChestZPos != null) { d2 += 0.5D; } if (this.adjacentChestXPos != null) { d1 += 0.5D; } this.world.playSound((EntityPlayer)null, d1, (double)j + 0.5D, d2, SoundEvents.BLOCK_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, this.world.rand.nextFloat() * 0.1F + 0.9F); } if (this.numPlayersUsing == 0 && this.lidAngle > 0.0F || this.numPlayersUsing > 0 && this.lidAngle < 1.0F) { float f2 = this.lidAngle; if (this.numPlayersUsing > 0) { this.lidAngle += 0.1F; } else { this.lidAngle -= 0.1F; } if (this.lidAngle > 1.0F) { this.lidAngle = 1.0F; } float f3 = 0.5F; if (this.lidAngle < 0.5F && f2 >= 0.5F && this.adjacentChestZNeg == null && this.adjacentChestXNeg == null) { double d3 = (double)i + 0.5D; double d0 = (double)k + 0.5D; if (this.adjacentChestZPos != null) { d0 += 0.5D; } if (this.adjacentChestXPos != null) { d3 += 0.5D; } this.world.playSound((EntityPlayer)null, d3, (double)j + 0.5D, d0, SoundEvents.BLOCK_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, this.world.rand.nextFloat() * 0.1F + 0.9F); } if (this.lidAngle < 0.0F) { this.lidAngle = 0.0F; } } } @Override public boolean receiveClientEvent(int id, int type) { if (id == 1) { this.numPlayersUsing = type; return true; } else { return super.receiveClientEvent(id, type); } } @Override public void openInventory(EntityPlayer player) { if (!player.isSpectator()) { if (this.numPlayersUsing < 0) { this.numPlayersUsing = 0; } ++this.numPlayersUsing; this.world.addBlockEvent(this.pos, this.getBlockType(), 1, this.numPlayersUsing); this.world.notifyNeighborsOfStateChange(this.pos, this.getBlockType(), false); if (this.getChestType() == BlockChest.Type.TRAP) { this.world.notifyNeighborsOfStateChange(this.pos.down(), this.getBlockType(), false); } } } @Override public void closeInventory(EntityPlayer player) { if (!player.isSpectator() && this.getBlockType() instanceof BlockChest) { --this.numPlayersUsing; this.world.addBlockEvent(this.pos, this.getBlockType(), 1, this.numPlayersUsing); this.world.notifyNeighborsOfStateChange(this.pos, this.getBlockType(), false); if (this.getChestType() == BlockChest.Type.TRAP) { this.world.notifyNeighborsOfStateChange(this.pos.down(), this.getBlockType(), false); } } } public net.minecraftforge.items.VanillaDoubleChestItemHandler doubleChestHandler; @SuppressWarnings("unchecked") @Override public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable net.minecraft.util.EnumFacing facing) { if (capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { if(doubleChestHandler == null || doubleChestHandler.needsRefresh()) doubleChestHandler = net.minecraftforge.items.VanillaDoubleChestItemHandler.get(this); if (doubleChestHandler != null && doubleChestHandler != net.minecraftforge.items.VanillaDoubleChestItemHandler.NO_ADJACENT_CHESTS_INSTANCE) return (T) doubleChestHandler; } return super.getCapability(capability, facing); } @Override public net.minecraftforge.items.IItemHandler getSingleChestHandler() { return super.getCapability(net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); } /** * invalidates a tile entity */ @Override public void invalidate() { super.invalidate(); this.updateContainingBlockInfo(); this.checkForAdjacentChests(); } @Override public BlockChest.Type getChestType() { if (this.cachedChestType == null) { if (this.world == null || !(this.getBlockType() instanceof BlockChest)) { return BlockChest.Type.BASIC; } this.cachedChestType = ((BlockChest)this.getBlockType()).chestType; } return this.cachedChestType; } public String getGuiID() { return "minecraft:chest"; } public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn) { this.fillWithLoot(playerIn); return new ContainerChest(playerInventory, this, playerIn); } protected NonNullList<ItemStack> getItems() { return this.chestContents; } } Extended on TileEntityChestRenderer: Spoiler @SideOnly(Side.CLIENT) public class ModTERChest extends TileEntityChestRenderer { private static final ResourceLocation TEXTURE_TRAPPED_DOUBLE = new ResourceLocation("textures/entity/chest/trapped_double.png"); private static final ResourceLocation TEXTURE_CHRISTMAS_DOUBLE = new ResourceLocation("textures/entity/chest/christmas_double.png"); private static final ResourceLocation TEXTURE_NORMAL_DOUBLE = new ResourceLocation("textures/entity/chest/normal_double.png"); private static final ResourceLocation TEXTURE_TRAPPED = new ResourceLocation("textures/entity/chest/trapped.png"); private static final ResourceLocation TEXTURE_CHRISTMAS = new ResourceLocation("textures/entity/chest/christmas.png"); private static final ResourceLocation TEXTURE_NORMAL = new ResourceLocation("textures/entity/chest/normal.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; } } public void renderTileEntityAt(TileEntityChest 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 BlockChest && i == 0) { ((BlockChest)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 if (te.getChestType() == BlockChest.Type.TRAP) { this.bindTexture(TEXTURE_TRAPPED); } else { this.bindTexture(TEXTURE_NORMAL); } } 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 if (te.getChestType() == BlockChest.Type.TRAP) { this.bindTexture(TEXTURE_TRAPPED_DOUBLE); } else { this.bindTexture(TEXTURE_NORMAL_DOUBLE); } } 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); } } } } created a guichest class extending guicontainer: Spoiler public class ModGuiChest extends GuiContainer{ /** The ResourceLocation containing the chest GUI texture. */ private static final ResourceLocation CHEST_GUI_TEXTURE = new ResourceLocation("textures/gui/container/generic_54.png"); private final IInventory upperChestInventory; private final IInventory lowerChestInventory; /** window height is calculated with these values; the more rows, the heigher */ private final int inventoryRows; public ModGuiChest(IInventory upperInv, IInventory lowerInv) { super(new ModContainerChest(upperInv, lowerInv, Minecraft.getMinecraft().player)); this.upperChestInventory = upperInv; this.lowerChestInventory = lowerInv; this.allowUserInput = false; int i = 222; int j = 114; this.inventoryRows = lowerInv.getSizeInventory() / 9; this.ySize = 114 + this.inventoryRows * 18; } /** * Draw the foreground layer for the GuiContainer (everything in front of the items) */ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { this.fontRendererObj.drawString(this.lowerChestInventory.getDisplayName().getUnformattedText(), 8, 6, 4210752); this.fontRendererObj.drawString(this.upperChestInventory.getDisplayName().getUnformattedText(), 8, this.ySize - 96 + 2, 4210752); } /** * Draws the background layer of this container (behind the items). */ protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(CHEST_GUI_TEXTURE); int i = (this.width - this.xSize) / 2; int j = (this.height - this.ySize) / 2; this.drawTexturedModalRect(i, j, 0, 0, this.xSize, this.inventoryRows * 18 + 17); this.drawTexturedModalRect(i, j + this.inventoryRows * 18 + 17, 0, 126, this.xSize, 96); } } Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 13, 20178 yr Author 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. :-) Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 13, 20178 yr Author Aha i found a small bug! When the chest is turned into a double chest, 1 part of the chest is not rendered when it is almost out of screen. This only happens with doublechest and only on the left side of the screen. I added 2 screenshots, so you can see what i mean: Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 13, 20178 yr 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.
May 13, 20178 yr 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.
May 13, 20178 yr Author 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? Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 14, 20178 yr 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.
May 14, 20178 yr Author 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 Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 14, 20178 yr 49 minutes ago, winnetrie said: It turns out that the tileentity gets always the id from the last instance i created of BlockModChest 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.
May 14, 20178 yr 1 hour ago, winnetrie said: When 1 tileentity is enough is 1 block also enough? 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 May 14, 20178 yr by Abastro I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
May 14, 20178 yr Author 29 minutes ago, 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. 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. Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 14, 20178 yr Author 20 minutes ago, 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. 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. Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 14, 20178 yr 6 minutes ago, winnetrie said: i'm not sure how to acces the enum from another class. Get it from the blockstate, it should be straightforward. About the rendering bug, do you detect whether the adjacent chest is removed? Edited May 14, 20178 yr by Abastro I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
May 14, 20178 yr Author 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> Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 14, 20178 yr 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.
May 14, 20178 yr Author Do you mean implementing IStringSerializable? That doesn't change anything. Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 14, 20178 yr Author 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: Spoiler public class BlockModChest extends BlockContainer { public static final PropertyDirection FACING = BlockHorizontal.FACING; public PropertyEnum<ChestTypeEnum> TYPE = PropertyEnum.<ChestTypeEnum>create("type",ChestTypeEnum.class); protected static final AxisAlignedBB NORTH_CHEST_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0D, 0.9375D, 0.875D, 0.9375D); protected static final AxisAlignedBB SOUTH_CHEST_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.875D, 1.0D); protected static final AxisAlignedBB WEST_CHEST_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0625D, 0.9375D, 0.875D, 0.9375D); protected static final AxisAlignedBB EAST_CHEST_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 1.0D, 0.875D, 0.9375D); protected static final AxisAlignedBB NOT_CONNECTED_AABB = new AxisAlignedBB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.875D, 0.9375D); /** 0 : Normal chest, 1 : Trapped chest */ public int CHEST_ID; public BlockModChest(String blockname, int blockID) { super(Material.WOOD); this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(TYPE, ChestTypeEnum.SPRUCE)); this.CHEST_ID = blockID; this.setCreativeTab(Tem.decortab); setUnlocalizedName(blockname); setRegistryName(blockname); } /** * Used to determine ambient occlusion and culling when rebuilding chunks for render */ public boolean isOpaqueCube(IBlockState state) { return false; } public boolean isFullCube(IBlockState state) { return false; } @Override @SideOnly(Side.CLIENT) public boolean hasCustomBreakingProgress(IBlockState state) { return true; } /** * The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only, * LIQUID for vanilla liquids, INVISIBLE to skip all rendering */ @Override public EnumBlockRenderType getRenderType(IBlockState state) { return EnumBlockRenderType.ENTITYBLOCK_ANIMATED; } @Override public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { return source.getBlockState(pos.north()).getBlock() == this ? NORTH_CHEST_AABB : (source.getBlockState(pos.south()).getBlock() == this ? SOUTH_CHEST_AABB : (source.getBlockState(pos.west()).getBlock() == this ? WEST_CHEST_AABB : (source.getBlockState(pos.east()).getBlock() == this ? EAST_CHEST_AABB : NOT_CONNECTED_AABB))); } /** * Called after the block is set in the Chunk data, but before the Tile Entity is set */ @Override public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state) { this.checkForSurroundingChests(worldIn, pos, state); for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL) { BlockPos blockpos = pos.offset(enumfacing); IBlockState iblockstate = worldIn.getBlockState(blockpos); if (iblockstate.getBlock() == this) { this.checkForSurroundingChests(worldIn, blockpos, iblockstate); } } } /** * Called by ItemBlocks just before a block is actually set in the world, to allow for adjustments to the * IBlockstate */ @Override public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer) { return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing()); } /** * Called by ItemBlocks after a block is set in the world, to allow post-place logic */ @Override public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { EnumFacing enumfacing = EnumFacing.getHorizontal(MathHelper.floor((double)(placer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3).getOpposite(); state = state.withProperty(FACING, enumfacing); BlockPos blockpos = pos.north(); BlockPos blockpos1 = pos.south(); BlockPos blockpos2 = pos.west(); BlockPos blockpos3 = pos.east(); boolean flag = this == worldIn.getBlockState(blockpos).getBlock(); boolean flag1 = this == worldIn.getBlockState(blockpos1).getBlock(); boolean flag2 = this == worldIn.getBlockState(blockpos2).getBlock(); boolean flag3 = this == worldIn.getBlockState(blockpos3).getBlock(); if (!flag && !flag1 && !flag2 && !flag3) { worldIn.setBlockState(pos, state, 3); } else if (enumfacing.getAxis() != EnumFacing.Axis.X || !flag && !flag1) { if (enumfacing.getAxis() == EnumFacing.Axis.Z && (flag2 || flag3)) { if (flag2) { worldIn.setBlockState(blockpos2, state, 3); } else { worldIn.setBlockState(blockpos3, state, 3); } worldIn.setBlockState(pos, state, 3); } } else { if (flag) { worldIn.setBlockState(blockpos, state, 3); } else { worldIn.setBlockState(blockpos1, state, 3); } worldIn.setBlockState(pos, state, 3); } if (stack.hasDisplayName()) { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof TileEntityModChest) { ((TileEntityModChest)tileentity).setCustomName(stack.getDisplayName()); } } } public IBlockState checkForSurroundingChests(World worldIn, BlockPos pos, IBlockState state) { if (worldIn.isRemote) { return state; } else { IBlockState iblockstate = worldIn.getBlockState(pos.north()); IBlockState iblockstate1 = worldIn.getBlockState(pos.south()); IBlockState iblockstate2 = worldIn.getBlockState(pos.west()); IBlockState iblockstate3 = worldIn.getBlockState(pos.east()); EnumFacing enumfacing = (EnumFacing)state.getValue(FACING); if (iblockstate.getBlock() != this && iblockstate1.getBlock() != this) { boolean flag = iblockstate.isFullBlock(); boolean flag1 = iblockstate1.isFullBlock(); if (iblockstate2.getBlock() == this || iblockstate3.getBlock() == this) { BlockPos blockpos1 = iblockstate2.getBlock() == this ? pos.west() : pos.east(); IBlockState iblockstate7 = worldIn.getBlockState(blockpos1.north()); IBlockState iblockstate6 = worldIn.getBlockState(blockpos1.south()); enumfacing = EnumFacing.SOUTH; EnumFacing enumfacing2; if (iblockstate2.getBlock() == this) { enumfacing2 = (EnumFacing)iblockstate2.getValue(FACING); } else { enumfacing2 = (EnumFacing)iblockstate3.getValue(FACING); } if (enumfacing2 == EnumFacing.NORTH) { enumfacing = EnumFacing.NORTH; } if ((flag || iblockstate7.isFullBlock()) && !flag1 && !iblockstate6.isFullBlock()) { enumfacing = EnumFacing.SOUTH; } if ((flag1 || iblockstate6.isFullBlock()) && !flag && !iblockstate7.isFullBlock()) { enumfacing = EnumFacing.NORTH; } } } else { BlockPos blockpos = iblockstate.getBlock() == this ? pos.north() : pos.south(); IBlockState iblockstate4 = worldIn.getBlockState(blockpos.west()); IBlockState iblockstate5 = worldIn.getBlockState(blockpos.east()); enumfacing = EnumFacing.EAST; EnumFacing enumfacing1; if (iblockstate.getBlock() == this) { enumfacing1 = (EnumFacing)iblockstate.getValue(FACING); } else { enumfacing1 = (EnumFacing)iblockstate1.getValue(FACING); } if (enumfacing1 == EnumFacing.WEST) { enumfacing = EnumFacing.WEST; } if ((iblockstate2.isFullBlock() || iblockstate4.isFullBlock()) && !iblockstate3.isFullBlock() && !iblockstate5.isFullBlock()) { enumfacing = EnumFacing.EAST; } if ((iblockstate3.isFullBlock() || iblockstate5.isFullBlock()) && !iblockstate2.isFullBlock() && !iblockstate4.isFullBlock()) { enumfacing = EnumFacing.WEST; } } state = state.withProperty(FACING, enumfacing); worldIn.setBlockState(pos, state, 3); return state; } } public IBlockState correctFacing(World worldIn, BlockPos pos, IBlockState state) { EnumFacing enumfacing = null; for (EnumFacing enumfacing1 : EnumFacing.Plane.HORIZONTAL) { IBlockState iblockstate = worldIn.getBlockState(pos.offset(enumfacing1)); if (iblockstate.getBlock() == this) { return state; } if (iblockstate.isFullBlock()) { if (enumfacing != null) { enumfacing = null; break; } enumfacing = enumfacing1; } } if (enumfacing != null) { return state.withProperty(FACING, enumfacing.getOpposite()); } else { EnumFacing enumfacing2 = (EnumFacing)state.getValue(FACING); if (worldIn.getBlockState(pos.offset(enumfacing2)).isFullBlock()) { enumfacing2 = enumfacing2.getOpposite(); } if (worldIn.getBlockState(pos.offset(enumfacing2)).isFullBlock()) { enumfacing2 = enumfacing2.rotateY(); } if (worldIn.getBlockState(pos.offset(enumfacing2)).isFullBlock()) { enumfacing2 = enumfacing2.getOpposite(); } return state.withProperty(FACING, enumfacing2); } } @Override public boolean canPlaceBlockAt(World worldIn, BlockPos pos) { int i = 0; BlockPos blockpos = pos.west(); BlockPos blockpos1 = pos.east(); BlockPos blockpos2 = pos.north(); BlockPos blockpos3 = pos.south(); if (worldIn.getBlockState(blockpos).getBlock() == this) { if (this.isDoubleChest(worldIn, blockpos)) { return false; } ++i; } if (worldIn.getBlockState(blockpos1).getBlock() == this) { if (this.isDoubleChest(worldIn, blockpos1)) { return false; } ++i; } if (worldIn.getBlockState(blockpos2).getBlock() == this) { if (this.isDoubleChest(worldIn, blockpos2)) { return false; } ++i; } if (worldIn.getBlockState(blockpos3).getBlock() == this) { if (this.isDoubleChest(worldIn, blockpos3)) { return false; } ++i; } return i <= 1; } private boolean isDoubleChest(World worldIn, BlockPos pos) { if (worldIn.getBlockState(pos).getBlock() != this) { return false; } else { for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL) { if (worldIn.getBlockState(pos.offset(enumfacing)).getBlock() == this) { return true; } } return false; } } /** * Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor * change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid * block, etc. */ @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(); } } /** * Called serverside after this block is replaced with another in Chunk, but before the Tile Entity is updated */ @Override public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof IInventory) { InventoryHelper.dropInventoryItems(worldIn, pos, (IInventory)tileentity); worldIn.updateComparatorOutputLevel(pos, this); } super.breakBlock(worldIn, pos, state); } /** * Called when the block is right clicked by a player. */ @Override public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { if (worldIn.isRemote) { return true; } else { ILockableContainer ilockablecontainer = this.getLockableContainer(worldIn, pos); if (ilockablecontainer != null) { playerIn.displayGUIChest(ilockablecontainer); playerIn.addStat(StatList.CHEST_OPENED); // if (this.chestType == BlockModChest.Type.BASIC) // { // playerIn.addStat(StatList.CHEST_OPENED); // } // else if (this.chestType == BlockModChest.Type.TRAP) // { // playerIn.addStat(StatList.TRAPPED_CHEST_TRIGGERED); // } } return true; } } @Nullable public ILockableContainer getLockableContainer(World worldIn, BlockPos pos) { return this.getContainer(worldIn, pos, false); } @Nullable public ILockableContainer getContainer(World p_189418_1_, BlockPos p_189418_2_, boolean p_189418_3_) { TileEntity tileentity = p_189418_1_.getTileEntity(p_189418_2_); if (!(tileentity instanceof TileEntityModChest)) { return null; } else { ILockableContainer ilockablecontainer = (TileEntityModChest)tileentity; if (!p_189418_3_ && this.isBlocked(p_189418_1_, p_189418_2_)) { return null; } else { for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL) { BlockPos blockpos = p_189418_2_.offset(enumfacing); Block block = p_189418_1_.getBlockState(blockpos).getBlock(); if (block == this) { if (this.isBlocked(p_189418_1_, blockpos)) { return null; } TileEntity tileentity1 = p_189418_1_.getTileEntity(blockpos); if (tileentity1 instanceof TileEntityModChest) { if (enumfacing != EnumFacing.WEST && enumfacing != EnumFacing.NORTH) { ilockablecontainer = new InventoryLargeChest("container.chestDouble", ilockablecontainer, (TileEntityModChest)tileentity1); } else { ilockablecontainer = new InventoryLargeChest("container.chestDouble", (TileEntityModChest)tileentity1, ilockablecontainer); } } } } return ilockablecontainer; } } } /** * Returns a new instance of a block's tile entity class. Called on placing the block. */ @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; } /** * Can this block provide power. Only wire currently seems to have this change based on its state. */ @Override public boolean canProvidePower(IBlockState state) { return false;//this.chestType == BlockModChest.Type.TRAP; } @Override public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) { if (!blockState.canProvidePower()) { return 0; } else { int i = 0; TileEntity tileentity = blockAccess.getTileEntity(pos); if (tileentity instanceof TileEntityModChest) { i = ((TileEntityModChest)tileentity).numPlayersUsing; } return MathHelper.clamp(i, 0, 15); } } @Override public int getStrongPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) { return side == EnumFacing.UP ? blockState.getWeakPower(blockAccess, pos, side) : 0; } private boolean isBlocked(World worldIn, BlockPos pos) { return this.isBelowSolidBlock(worldIn, pos) || this.isOcelotSittingOnChest(worldIn, pos); } private boolean isBelowSolidBlock(World worldIn, BlockPos pos) { return worldIn.getBlockState(pos.up()).isSideSolid(worldIn, pos.up(), EnumFacing.DOWN); } private boolean isOcelotSittingOnChest(World worldIn, BlockPos pos) { for (Entity entity : worldIn.getEntitiesWithinAABB(EntityOcelot.class, new AxisAlignedBB((double)pos.getX(), (double)(pos.getY() + 1), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 2), (double)(pos.getZ() + 1)))) { EntityOcelot entityocelot = (EntityOcelot)entity; if (entityocelot.isSitting()) { return true; } } return false; } @Override public boolean hasComparatorInputOverride(IBlockState state) { return true; } @Override public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos) { return Container.calcRedstoneFromInventory(this.getLockableContainer(worldIn, pos)); } /** * Convert the given metadata into a BlockState for this Block */ @Override public IBlockState getStateFromMeta(int meta) { EnumFacing enumfacing = EnumFacing.getFront(meta); if (enumfacing.getAxis() == EnumFacing.Axis.Y) { enumfacing = EnumFacing.NORTH; } return this.getDefaultState().withProperty(FACING, enumfacing); } /** * Convert the BlockState into the correct metadata value */ @Override public int getMetaFromState(IBlockState state) { return ((EnumFacing)state.getValue(FACING)).getIndex(); } /** * Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed * blockstate. */ @Override public IBlockState withRotation(IBlockState state, Rotation rot) { return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING))); } /** * Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed * blockstate. */ @Override public IBlockState withMirror(IBlockState state, Mirror mirrorIn) { return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING))); } @Override protected BlockStateContainer createBlockState() { return new BlockStateContainer(this, new IProperty[] {FACING, TYPE}); } /* ======================================== FORGE START =====================================*/ @Override public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis) { return !isDoubleChest(world, pos) && super.rotateBlock(world, pos, axis); } } This results now in crashing the game. Spoiler [14:44:20] [Client thread/ERROR] [FML]: The following problems were captured during this phase [14:44:20] [Client thread/ERROR] [FML]: Caught exception from Tim's Expansion Mod (tem) java.lang.NullPointerException at net.minecraft.block.state.BlockStateContainer.validateProperty(BlockStateContainer.java:103) ~[forgeSrc-1.11.2-13.20.0.2282.jar:?] at net.minecraft.block.state.BlockStateContainer.<init>(BlockStateContainer.java:77) ~[forgeSrc-1.11.2-13.20.0.2282.jar:?] at net.minecraft.block.state.BlockStateContainer.<init>(BlockStateContainer.java:62) ~[forgeSrc-1.11.2-13.20.0.2282.jar:?] at winnetrie.tem.blocks.BlockModChest.createBlockState(BlockModChest.java:683) ~[bin/:?] at net.minecraft.block.Block.<init>(Block.java:284) ~[forgeSrc-1.11.2-13.20.0.2282.jar:?] at net.minecraft.block.BlockContainer.<init>(BlockContainer.java:30) ~[forgeSrc-1.11.2-13.20.0.2282.jar:?] at net.minecraft.block.BlockContainer.<init>(BlockContainer.java:25) ~[forgeSrc-1.11.2-13.20.0.2282.jar:?] at winnetrie.tem.blocks.BlockModChest.<init>(BlockModChest.java:61) ~[bin/:?] at winnetrie.tem.init.ModBlocks.init(ModBlocks.java:333) ~[bin/:?] at winnetrie.tem.Tem.preInit(Tem.java:65) ~[bin/:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_73] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_73] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_73] at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_73] at net.minecraftforge.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:643) ~[forgeSrc-1.11.2-13.20.0.2282.jar:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_73] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_73] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_73] at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_73] at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) ~[guava-17.0.jar:?] at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) ~[guava-17.0.jar:?] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) ~[guava-17.0.jar:?] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) ~[guava-17.0.jar:?] at com.google.common.eventbus.EventBus.post(EventBus.java:275) ~[guava-17.0.jar:?] at net.minecraftforge.fml.common.LoadController.sendEventToModContainer(LoadController.java:246) ~[forgeSrc-1.11.2-13.20.0.2282.jar:?] at net.minecraftforge.fml.common.LoadController.propogateStateMessage(LoadController.java:224) ~[forgeSrc-1.11.2-13.20.0.2282.jar:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_73] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_73] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_73] at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_73] at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) ~[guava-17.0.jar:?] at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) ~[guava-17.0.jar:?] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) ~[guava-17.0.jar:?] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) ~[guava-17.0.jar:?] at com.google.common.eventbus.EventBus.post(EventBus.java:275) ~[guava-17.0.jar:?] at net.minecraftforge.fml.common.LoadController.distributeStateMessage(LoadController.java:147) [LoadController.class:?] at net.minecraftforge.fml.common.Loader.preinitializeMods(Loader.java:647) [Loader.class:?] at net.minecraftforge.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:275) [FMLClientHandler.class:?] at net.minecraft.client.Minecraft.init(Minecraft.java:478) [Minecraft.class:?] at net.minecraft.client.Minecraft.run(Minecraft.java:387) [Minecraft.class:?] at net.minecraft.client.main.Main.main(Main.java:118) [Main.class:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_73] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_73] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_73] at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_73] at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?] at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_73] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_73] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_73] at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_73] at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) [start/:?] at GradleStart.main(GradleStart.java:26) [start/:?] [14:44:20] [Client thread/INFO] [STDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:600]: ---- Minecraft Crash Report ---- // Daisy, daisy... Time: 5/14/17 2:44 PM Description: There was a severe problem during mod loading that has caused the game to fail net.minecraftforge.fml.common.LoaderExceptionModCrash: Caught exception from Tim's Expansion Mod (tem) Caused by: java.lang.NullPointerException at net.minecraft.block.state.BlockStateContainer.validateProperty(BlockStateContainer.java:103) at net.minecraft.block.state.BlockStateContainer.<init>(BlockStateContainer.java:77) at net.minecraft.block.state.BlockStateContainer.<init>(BlockStateContainer.java:62) at winnetrie.tem.blocks.BlockModChest.createBlockState(BlockModChest.java:683) at net.minecraft.block.Block.<init>(Block.java:284) at net.minecraft.block.BlockContainer.<init>(BlockContainer.java:30) at net.minecraft.block.BlockContainer.<init>(BlockContainer.java:25) at winnetrie.tem.blocks.BlockModChest.<init>(BlockModChest.java:61) at winnetrie.tem.init.ModBlocks.init(ModBlocks.java:333) at winnetrie.tem.Tem.preInit(Tem.java:65) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at net.minecraftforge.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:643) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) at com.google.common.eventbus.EventBus.post(EventBus.java:275) at net.minecraftforge.fml.common.LoadController.sendEventToModContainer(LoadController.java:246) at net.minecraftforge.fml.common.LoadController.propogateStateMessage(LoadController.java:224) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) at com.google.common.eventbus.EventBus.post(EventBus.java:275) at net.minecraftforge.fml.common.LoadController.distributeStateMessage(LoadController.java:147) at net.minecraftforge.fml.common.Loader.preinitializeMods(Loader.java:647) at net.minecraftforge.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:275) at net.minecraft.client.Minecraft.init(Minecraft.java:478) at net.minecraft.client.Minecraft.run(Minecraft.java:387) at net.minecraft.client.main.Main.main(Main.java:118) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) at net.minecraft.launchwrapper.Launch.main(Launch.java:28) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) at GradleStart.main(GradleStart.java:26) Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 14, 20178 yr Author 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. Edited May 14, 20178 yr by winnetrie Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 14, 20178 yr Author 12 hours ago, Abastro said: Get it from the blockstate, it should be straightforward. About the rendering bug, do you detect whether the adjacent chest is removed? 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 May 14, 20178 yr by winnetrie Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 15, 20178 yr 1 hour ago, winnetrie said: How exactly do i detect this? Is there a method for it? 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.
May 15, 20178 yr Author 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 Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
May 15, 20178 yr You need to update the rendering, call World::markAndNotifyBlock with flag 3.(the flag is explained on World::setBlock) Edited May 15, 20178 yr 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.
May 15, 20178 yr Author 15 minutes ago, Abastro said: You need to update the rendering, call World::markAndNotifyBlock with flag 3.(the flag is explained on World::setBlock) Where do i place this exactly? In de tesr? Try out my new Modpack for MC 1.15.2 https://www.curseforge.com/minecraft/modpacks/terran-civilization
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.