User Tools

Site Tools


tutorial:containers

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
Next revisionBoth sides next revision
tutorial:containers [2020/02/27 13:31] – new tutorial mkpolitutorial:containers [2020/04/02 11:04] – [Block and BlockItem] Replace BlockWithEntity with BlockEntityProvider and other cleanup earthcomputer
Line 3: Line 3:
  
 ==== Block and BlockItem ==== ==== Block and BlockItem ====
-First create and register our block and BlockItem+First we need to create the Block and register it as well as its BlockItem.
  
-<code java [enable_line_numbers="true"]> +<code java [enable_line_numbers="true"BiggerChestBlock.java
-public class BiggerChestBlock extends BlockWithEntity {+public class BiggerChestBlock extends Block implements BlockEntityProvider {
     public BiggerChestBlock(Settings settings) {     public BiggerChestBlock(Settings settings) {
         super(settings);         super(settings);
-    } 
- 
-    // We need to explicitly return a MODEL render type because BlockWithEntity has a side-effect of not showing the model. 
-    // You can also implement BlockEntityProvider Type to avoid this side-effect. 
-    public BlockRenderType getRenderType(BlockState state) { 
-        return BlockRenderType.MODEL; 
     }     }
  
     // We will create the BlockEntity later.     // We will create the BlockEntity later.
 +    @Override
     public BlockEntity createBlockEntity(BlockView view) {     public BlockEntity createBlockEntity(BlockView view) {
         return new BiggerChestBlockEntity();         return new BiggerChestBlockEntity();
     }     }
  
 +    @Override
     public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {     public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
         if (itemStack.hasCustomName()) {         if (itemStack.hasCustomName()) {
Line 31: Line 27:
     }     }
  
 +    @Override
     public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {     public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
         if (!world.isClient) {         if (!world.isClient) {
Line 42: Line 39:
  
     // Scatter the items in the chest when it is removed.     // Scatter the items in the chest when it is removed.
 +    @Override
     public void onBlockRemoved(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {     public void onBlockRemoved(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
         if (state.getBlock() != newState.getBlock()) {         if (state.getBlock() != newState.getBlock()) {
Line 47: Line 45:
             if (blockEntity instanceof BiggerChestBlockEntity) {             if (blockEntity instanceof BiggerChestBlockEntity) {
                 ItemScatterer.spawn(world, (BlockPos)pos, (Inventory)((BiggerChestBlockEntity)blockEntity));                 ItemScatterer.spawn(world, (BlockPos)pos, (Inventory)((BiggerChestBlockEntity)blockEntity));
 +                // update comparators
                 world.updateHorizontalAdjacent(pos, this);                 world.updateHorizontalAdjacent(pos, this);
             }             }
Line 53: Line 52:
     }     }
  
 +    @Override
     public boolean hasComparatorOutput(BlockState state) {     public boolean hasComparatorOutput(BlockState state) {
         return true;         return true;
     }     }
  
 +    @Override
     public int getComparatorOutput(BlockState state, World world, BlockPos pos) {     public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
         return Container.calculateComparatorOutput(world.getBlockEntity(pos));         return Container.calculateComparatorOutput(world.getBlockEntity(pos));
Line 65: Line 66:
 Then we need to register our Block and BlockItem. Then we need to register our Block and BlockItem.
  
-<code java [enable_line_numbers="true"]>+<code java [enable_line_numbers="true"ExampleMod.java>
 public class ExampleMod implements ModInitializer public class ExampleMod implements ModInitializer
 { {
Line 84: Line 85:
 } }
 </code> </code>
 +
 +You may refer to other tutorials to modify the appearance and other properties of the Block by adding models or adjusting rendering later.
  
 ==== BlockEntity ==== ==== BlockEntity ====
-We then need to add an ''onUse'' method in our Block class in order to open our chest.+BlockEntity is used for managing container inventories. Actually, it implements Inventory interface. It is required to save and load the inventory.
  
-<code java> +<code java [enable_line_numbers="true"] BiggerChestBlockEntity.java> 
-    +public class BiggerChestBlockEntity extends LootableContainerBlockEntity { 
 +    private DefaultedList<ItemStack> inventory; 
 +    private static final int INVENTORY_SIZE = 54; // 9 * 6 = 54 
 + 
 +    public BiggerChestBlockEntity() { 
 +        super(ExampleMod.BIGGER_CHEST_ENTITY_TYPE); 
 +        this.inventory = DefaultedList.ofSize(INVENTORY_SIZE, ItemStack.EMPTY); 
 +    } 
 + 
 +    @Override 
 +    protected Text getContainerName() { 
 +        return new TranslatableText("container.chest"); 
 +    } 
 + 
 +    @Override 
 +    protected Container createContainer(int syncId, PlayerInventory playerInventory) { 
 +        return new BiggerChestContainer(syncId, playerInventory, (Inventory) this); 
 +    } 
 + 
 +    @Override 
 +    protected DefaultedList<ItemStack> getInvStackList() { 
 +        return this.inventory; 
 +    } 
 + 
 +    @Override 
 +    protected void setInvStackList(DefaultedList<ItemStack> list) { 
 +        this.inventory = list; 
 +    } 
 + 
 +    @Override 
 +    public int getInvSize() { 
 +        return INVENTORY_SIZE; 
 +    } 
 + 
 +    @Override 
 +    public void fromTag(CompoundTag tag) { 
 +        super.fromTag(tag); 
 +        this.inventory = DefaultedList.ofSize(this.getInvSize(), ItemStack.EMPTY); 
 +        if (!this.deserializeLootTable(tag)) { 
 +            Inventories.fromTag(tag, this.inventory); 
 +        } 
 +    } 
 + 
 +    @Override 
 +    public CompoundTag toTag(CompoundTag tag) { 
 +        super.toTag(tag); 
 +        if (!this.serializeLootTable(tag)) { 
 +            Inventories.toTag(tag, this.inventory); 
 +        } 
 +        return tag; 
 +    } 
 +}
 </code> </code>
  
Line 201: Line 255:
         [...]         [...]
         ContainerProviderRegistry.INSTANCE.registerFactory(BIGGER_CHEST, (syncId, identifier, player, buf) -> {         ContainerProviderRegistry.INSTANCE.registerFactory(BIGGER_CHEST, (syncId, identifier, player, buf) -> {
-            final BlockEntity blockEntity = player.world.getBlockEntity(buf.readBlockPos()); +            final World world = player.world
-            return((BiggerChestBlockEntityblockEntity).createContainer(syncId, player.inventory);+            final BlockPos pos = buf.readBlockPos(); 
 +            return world.getBlockState(pos).createContainerFactory(player.world, pos).createMenu(syncId, player.inventory, player);
         });         });
     }     }
Line 214: Line 269:
 </code> </code>
  
-==== Orgnizing ==== +==== Organizing ==== 
-After following  +After all the steps, you should have your ExampleMod Class and ExampleClientMod Class as such:
- +
-You should have your ExampleMod Class and ExampleClientMod Class as such:+
  
 <code java [enable_line_numbers="true"] ExampleMod.java> <code java [enable_line_numbers="true"] ExampleMod.java>
Line 246: Line 299:
     }     }
 </code> </code>
 +
 +{{tutorial:bigger_chest.png}}
  
 It's over and enjoy your custom container! It's over and enjoy your custom container!
tutorial/containers.txt · Last modified: 2022/05/27 15:57 by solidblock