tutorial:screenhandler
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision | ||
tutorial:screenhandler [2020/08/14 17:25] – manymoney2 | tutorial:screenhandler [2023/09/14 01:42] – [ScreenHandler and Screen] wjz_p | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Creating a Container Block (DRAFT) (NEW) ====== | + | ====== Creating a Container Block====== |
- | In this tutorial we will create simple | + | In this tutorial we will create simple |
Let us first explain some vocabulary: | Let us first explain some vocabulary: | ||
**Screenhandler: | **Screenhandler: | ||
- | A ScreenHandler is a class responsible for Synchronizing | + | A '' |
+ | Our subclass will have two constructors here: one will be used on the server side and will contain the real '' | ||
**Screen:** | **Screen:** | ||
- | The Screen class only exists on the client and will render the background and other decorations for your ScreenHandler | + | The '' |
- | Tutorials based on this: | ||
- | |||
- | - [[tutorial: | ||
- | |||
- | - [[tutorial: | ||
- | ===== Further Reading ===== | ||
- | This and the following Tutorials are heavily inspired by the ScreenHandlerAPI ExampleMod. | ||
- | It can be found here: [[https:// | ||
- | |||
- | The documentation for the Fabric ScreenHandlerAPI can be found here: ##javadoc link here## | ||
===== Block and BlockEntity classes ===== | ===== Block and BlockEntity classes ===== | ||
- | First we need to create the Block and its BlockEntity | + | First we need to create the '' |
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
Line 32: | Line 23: | ||
@Override | @Override | ||
- | public BlockEntity createBlockEntity(BlockView world) { | + | public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { |
- | return new BoxBlockEntity(); | + | return new BoxBlockEntity(pos, state); |
} | } | ||
Line 45: | Line 36: | ||
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) { | ||
- | //This will call the createScreenHandlerFactory method from blockWithEntity, which will return our blockEntity casted | + | //This will call the createScreenHandlerFactory method from BlockWithEntity, which will return our blockEntity casted |
- | //to a namedScreenHandlerFactory | + | //a namedScreenHandlerFactory. If your block class does not extend BlockWithEntity, |
NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, | NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, | ||
Line 79: | Line 70: | ||
@Override | @Override | ||
public int getComparatorOutput(BlockState state, World world, BlockPos pos) { | public int getComparatorOutput(BlockState state, World world, BlockPos pos) { | ||
- | return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)) | + | return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)); |
} | } | ||
} | } | ||
</ | </ | ||
- | Now we will create our BlockEntity, | + | Now we will create our '' |
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
Line 90: | Line 81: | ||
private final DefaultedList< | private final DefaultedList< | ||
- | public BoxBlockEntity() { | + | public BoxBlockEntity(BlockPos pos, BlockState state) { |
- | super(ExampleMod.BOX_BLOCK_ENTITY); | + | super(ExampleMod.BOX_BLOCK_ENTITY, pos, state); |
} | } | ||
Line 100: | Line 91: | ||
public DefaultedList< | public DefaultedList< | ||
return inventory; | return inventory; | ||
- | |||
} | } | ||
Line 116: | Line 106: | ||
@Override | @Override | ||
public Text getDisplayName() { | public Text getDisplayName() { | ||
- | return new TranslatableText(getCachedState().getBlock().getTranslationKey()); | + | |
+ | return Text.translatable(getCachedState().getBlock().getTranslationKey()); | ||
+ | // for earlier versions | ||
+ | // return new TranslatableText(getCachedState().getBlock().getTranslationKey()); | ||
} | } | ||
| | ||
@Override | @Override | ||
- | public void fromTag(BlockState state, CompoundTag tag) { | + | public void readNbt(NbtCompound nbt) { |
- | super.fromTag(state, tag); | + | super.readNbt(nbt); |
- | inventory = DefaultedList.ofSize(invsize, | + | Inventories.readNbt(nbt, this.inventory); |
- | Inventories.fromTag(tag, this.inventory); | + | |
} | } | ||
@Override | @Override | ||
- | public | + | public |
- | super.toTag(tag); | + | super.writeNbt(nbt); |
- | Inventories.toTag(tag, this.inventory); | + | Inventories.writeNbt(nbt, this.inventory); |
- | return | + | return |
} | } | ||
} | } | ||
Line 152: | Line 144: | ||
static { | static { | ||
- | BOX_BLOCK = Registry.register(Registry.BLOCK, BOX, new BoxBlock(FabricBlockSettings.copyOf(Blocks.CHEST))); | + | BOX_BLOCK = Registry.register(Registries.BLOCK, BOX, new BoxBlock(FabricBlockSettings.copyOf(Blocks.CHEST))); |
- | BOX_BLOCK_ITEM = Registry.register(Registry.ITEM, BOX, new BlockItem(BOX_BLOCK, | + | BOX_BLOCK_ITEM = Registry.register(Registries.ITEM, BOX, new BlockItem(BOX_BLOCK, |
//The parameter of build at the very end is always null, do not worry about it | //The parameter of build at the very end is always null, do not worry about it | ||
+ | // pre-1.17 | ||
BOX_BLOCK_ENTITY = Registry.register(Registry.BLOCK_ENTITY_TYPE, | BOX_BLOCK_ENTITY = Registry.register(Registry.BLOCK_ENTITY_TYPE, | ||
+ | // In 1.17 use FabricBlockEntityTypeBuilder instead of BlockEntityType.Builder | ||
+ | BOX_BLOCK_ENTITY = Registry.register(Registry.BLOCK_ENTITY_TYPE, | ||
} | } | ||
Line 170: | Line 165: | ||
===== ScreenHandler and Screen ===== | ===== ScreenHandler and Screen ===== | ||
- | We need a ScreenHandler | + | As explained earlier, we need both a '' |
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
Line 178: | Line 173: | ||
//This constructor gets called on the client when the server wants it to open the screenHandler, | //This constructor gets called on the client when the server wants it to open the screenHandler, | ||
//The client will call the other constructor with an empty Inventory and the screenHandler will automatically | //The client will call the other constructor with an empty Inventory and the screenHandler will automatically | ||
- | //sync this empty inventory with the inventory on the server | + | //sync this empty inventory with the inventory on the server. |
public BoxScreenHandler(int syncId, PlayerInventory playerInventory) { | public BoxScreenHandler(int syncId, PlayerInventory playerInventory) { | ||
this(syncId, | this(syncId, | ||
Line 184: | Line 179: | ||
//This constructor gets called from the BlockEntity on the server without calling the other constructor first, the server knows the inventory of the container | //This constructor gets called from the BlockEntity on the server without calling the other constructor first, the server knows the inventory of the container | ||
- | //and can therefore directly provide it as an argument. This inventory will then be synced to the Client | + | //and can therefore directly provide it as an argument. This inventory will then be synced to the client. |
public BoxScreenHandler(int syncId, PlayerInventory playerInventory, | public BoxScreenHandler(int syncId, PlayerInventory playerInventory, | ||
super(ExampleMod.BOX_SCREEN_HANDLER, | super(ExampleMod.BOX_SCREEN_HANDLER, | ||
Line 250: | Line 245: | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
- | public class BoxScreen extends HandledScreen< | + | public class BoxScreen extends HandledScreen< |
//A path to the gui texture. In this example we use the texture from the dispenser | //A path to the gui texture. In this example we use the texture from the dispenser | ||
private static final Identifier TEXTURE = new Identifier(" | private static final Identifier TEXTURE = new Identifier(" | ||
- | public BoxScreen(ScreenHandler | + | public BoxScreen(BoxScreenHandler |
super(handler, | super(handler, | ||
} | } | ||
Line 260: | Line 255: | ||
@Override | @Override | ||
protected void drawBackground(MatrixStack matrices, float delta, int mouseX, int mouseY) { | protected void drawBackground(MatrixStack matrices, float delta, int mouseX, int mouseY) { | ||
- | RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); | + | RenderSystem.setShader(GameRenderer:: |
- | | + | RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); |
+ | | ||
int x = (width - backgroundWidth) / 2; | int x = (width - backgroundWidth) / 2; | ||
int y = (height - backgroundHeight) / 2; | int y = (height - backgroundHeight) / 2; | ||
drawTexture(matrices, | drawTexture(matrices, | ||
+ | //in 1.20 or above,this method is in DrawContext class. | ||
} | } | ||
Line 286: | Line 283: | ||
- | As Screens are are client only concept, we can only register them on the client | + | As screens |
- | <code java [enable_line_numbers=" | + | <code java [enable_line_numbers=" |
@Environment(EnvType.CLIENT) | @Environment(EnvType.CLIENT) | ||
Line 294: | Line 291: | ||
@Override | @Override | ||
public void onInitializeClient() { | public void onInitializeClient() { | ||
- | | + | |
} | } | ||
} | } | ||
Line 300: | Line 297: | ||
</ | </ | ||
- | ScreenHandlers | + | Don't forget to register this entrypoint in '' |
+ | <code json> | ||
+ | /* ... */ | ||
+ | " | ||
+ | /* ... */ | ||
+ | " | ||
+ | " | ||
+ | ] | ||
+ | }, | ||
+ | </ | ||
+ | |||
+ | '' | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
Line 326: | Line 334: | ||
{{: | {{: | ||
+ | |||
+ | ===== Further Reading ===== | ||
+ | - [[tutorial: | ||
+ | |||
+ | - [[tutorial: | ||
+ | |||
+ | - An example mod using the '' | ||
tutorial/screenhandler.txt · Last modified: 2024/02/19 02:51 by netuserget