tutorial:containers
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tutorial:containers [2020/02/27 16:19] – [Orgnizing] typo mkpoli | tutorial:containers [2022/05/27 15:57] (current) – solidblock | ||
|---|---|---|---|
| Line 3: | Line 3: | ||
| ==== Block and BlockItem ==== | ==== Block and BlockItem ==== | ||
| - | First we need to create Block and register it as well as its BlockItem. | + | First we need to create |
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| Line 10: | Line 10: | ||
| super(settings); | super(settings); | ||
| } | } | ||
| - | + | | |
| - | // We need to explicitly return a MODEL render type because BlockWithEntity has a side-effect of not showing | + | // A side effect of extending BlockWithEntity is it changes |
| - | | + | |
| public BlockRenderType getRenderType(BlockState state) { | public BlockRenderType getRenderType(BlockState state) { | ||
| return BlockRenderType.MODEL; | return BlockRenderType.MODEL; | ||
| Line 18: | Line 18: | ||
| // 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 33: | ||
| } | } | ||
| + | @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 45: | ||
| // 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()) { | ||
| BlockEntity blockEntity = world.getBlockEntity(pos); | BlockEntity blockEntity = world.getBlockEntity(pos); | ||
| if (blockEntity instanceof BiggerChestBlockEntity) { | if (blockEntity instanceof BiggerChestBlockEntity) { | ||
| - | ItemScatterer.spawn(world, | + | ItemScatterer.spawn(world, |
| + | // update comparators | ||
| world.updateHorizontalAdjacent(pos, | world.updateHorizontalAdjacent(pos, | ||
| } | } | ||
| Line 53: | Line 58: | ||
| } | } | ||
| + | @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 74: | Line 81: | ||
| public static final Identifier BIGGER_CHEST = new Identifier(MOD_ID, | public static final Identifier BIGGER_CHEST = new Identifier(MOD_ID, | ||
| - | public static final Block BIGGER_CHEST_BLOCK = new BiggerChestBlock(FabricBlockSettings.of(Material.METAL).build()); | + | public static final Block BIGGER_CHEST_BLOCK = new BiggerChestBlock(FabricBlockSettings.of(Material.METAL)); |
| @Override | @Override | ||
| Line 80: | Line 87: | ||
| { | { | ||
| Registry.register(Registry.BLOCK, | Registry.register(Registry.BLOCK, | ||
| - | Registry.register(Registry.BLOCK, BIGGER_CHEST, | + | Registry.register(Registry.ITEM, BIGGER_CHEST, |
| } | } | ||
| } | } | ||
| </ | </ | ||
| + | |||
| + | 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 ==== | ||
| - | BlockEntities are used for managing container inventories. Actually, it implements Inventory interface. | + | BlockEntity is used for managing container inventories. Actually, it implements Inventory interface. It is required to save and load the inventory. |
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| Line 100: | Line 109: | ||
| @Override | @Override | ||
| protected Text getContainerName() { | protected Text getContainerName() { | ||
| + | // versions 1.18.2 and below | ||
| return new TranslatableText(" | return new TranslatableText(" | ||
| + | // versions since 1.19 | ||
| + | return Text.translatable(" | ||
| } | } | ||
| @Override | @Override | ||
| - | protected | + | protected |
| - | return new BiggerChestContainer(syncId, playerInventory, | + | return new BiggerChestScreenHandler(syncId, playerInventory, |
| } | } | ||
| Line 119: | Line 131: | ||
| @Override | @Override | ||
| - | public int getInvSize() { | + | public int size() { |
| return INVENTORY_SIZE; | return INVENTORY_SIZE; | ||
| } | } | ||
| Line 126: | Line 138: | ||
| public void fromTag(CompoundTag tag) { | public void fromTag(CompoundTag tag) { | ||
| super.fromTag(tag); | super.fromTag(tag); | ||
| - | this.inventory = DefaultedList.ofSize(this.getInvSize(), ItemStack.EMPTY); | + | this.inventory = DefaultedList.ofSize(this.size(), ItemStack.EMPTY); |
| if (!this.deserializeLootTable(tag)) { | if (!this.deserializeLootTable(tag)) { | ||
| Inventories.fromTag(tag, | Inventories.fromTag(tag, | ||
| Line 144: | Line 156: | ||
| ==== Container GUI and Screen ==== | ==== Container GUI and Screen ==== | ||
| - | We need a Container | + | We need a ScreenHandler |
| - | <code java [enable_line_numbers=" | + | <code java [enable_line_numbers=" |
| - | public class BiggerChestContainer | + | public class BiggerChestScreenHandler |
| private final Inventory inventory; // Chest inventory | private final Inventory inventory; // Chest inventory | ||
| private static final int INVENTORY_SIZE = 54; // 6 rows * 9 cols | private static final int INVENTORY_SIZE = 54; // 6 rows * 9 cols | ||
| - | protected | + | protected |
| - | super(null, syncId); // Since we didn't create a ContainerType, we will place null here. | + | super(null, syncId); // Since we didn't create a ScreenHandlerType, we will place null here. |
| this.inventory = inventory; | this.inventory = inventory; | ||
| - | | + | |
| - | inventory.onInvOpen(playerInventory.player); | + | inventory.onOpen(playerInventory.player); |
| - | // Creating Slots for GUI. A Slot is essentially a correspoding | + | // Creating Slots for GUI. A Slot is essentially a corresponding |
| int i; | int i; | ||
| int j; | int j; | ||
| Line 184: | Line 196: | ||
| @Override | @Override | ||
| public boolean canUse(PlayerEntity player) { | public boolean canUse(PlayerEntity player) { | ||
| - | return this.inventory.canPlayerUseInv(player); | + | return this.inventory.canPlayerUse(player); |
| } | } | ||
| // Shift + Player Inv Slot | // Shift + Player Inv Slot | ||
| + | @Override | ||
| public ItemStack transferSlot(PlayerEntity player, int invSlot) { | public ItemStack transferSlot(PlayerEntity player, int invSlot) { | ||
| ItemStack newStack = ItemStack.EMPTY; | ItemStack newStack = ItemStack.EMPTY; | ||
| Line 215: | Line 228: | ||
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| - | public class BiggerChestScreen extends | + | public class BiggerChestScreen extends |
| // a path to gui texture, you may replace it with new Identifier(YourMod.MOD_ID, | // a path to gui texture, you may replace it with new Identifier(YourMod.MOD_ID, | ||
| private static final Identifier TEXTURE = new Identifier(" | private static final Identifier TEXTURE = new Identifier(" | ||
| - | public BiggerChestScreen(BiggerChestContainer container, PlayerInventory playerInventory, | + | public BiggerChestScreen(BiggerChestScreenHandler handler, PlayerInventory playerInventory, |
| - | super(container, playerInventory, | + | super(handler, playerInventory, |
| - | this.containerHeight | + | this.backgroundHeight |
| } | } | ||
| @Override | @Override | ||
| - | protected void drawForeground(int mouseX, int mouseY) { | + | protected void drawForeground(MatrixStack matrices, |
| - | this.font.draw(this.title.asFormattedString(), 8.0F, 6.0F, 4210752); | + | this.textRenderer.draw(matrices, |
| - | this.font.draw(this.playerInventory.getDisplayName().asFormattedString(), 8.0F, (float)(this.containerHeight | + | this.textRenderer.draw(matrices, |
| } | } | ||
| Line 234: | Line 247: | ||
| protected void drawBackground(float delta, int mouseX, int mouseY) { | protected void drawBackground(float delta, int mouseX, int mouseY) { | ||
| RenderSystem.color4f(1.0F, | RenderSystem.color4f(1.0F, | ||
| - | this.minecraft.getTextureManager().bindTexture(TEXTURE); | + | this.client.getTextureManager().bindTexture(TEXTURE); |
| - | int i = (this.width - this.containerWidth) / 2; | + | int i = (this.width - this.backgroundWidth) / 2; |
| - | int j = (this.height - this.containerHeight) / 2; | + | int j = (this.height - this.backgroundHeight) / 2; |
| - | this.blit(i, | + | this.blit(i, |
| - | this.blit(i, | + | this.blit(i, |
| } | } | ||
| } | } | ||
| Line 249: | Line 262: | ||
| public static final String BIGGER_CHEST_TRANSLATION_KEY = Util.createTranslationKey(" | public static final String BIGGER_CHEST_TRANSLATION_KEY = Util.createTranslationKey(" | ||
| + | @Override | ||
| public void onInitialize() { | public void onInitialize() { | ||
| [...] | [...] | ||
| ContainerProviderRegistry.INSTANCE.registerFactory(BIGGER_CHEST, | ContainerProviderRegistry.INSTANCE.registerFactory(BIGGER_CHEST, | ||
| - | final BlockEntity blockEntity | + | final World world = player.world; |
| - | return((BiggerChestBlockEntity) blockEntity).createContainer(syncId, player.inventory); | + | final BlockPos pos = buf.readBlockPos(); |
| + | return | ||
| }); | }); | ||
| } | } | ||
| Line 259: | Line 274: | ||
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| + | @Override | ||
| public void onInitializeClient() { | public void onInitializeClient() { | ||
| [...] | [...] | ||
| - | ScreenProviderRegistry.INSTANCE.< | + | ScreenProviderRegistry.INSTANCE.< |
| } | } | ||
| </ | </ | ||
| Line 292: | Line 308: | ||
| @Override | @Override | ||
| public void onInitializeClient() { | public void onInitializeClient() { | ||
| - | ScreenProviderRegistry.INSTANCE.< | + | ScreenProviderRegistry.INSTANCE.< |
| } | } | ||
| </ | </ | ||
tutorial/containers.1582820388.txt.gz · Last modified: 2020/02/27 16:19 by mkpoli