zh_cn:tutorial:screenhandler
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| zh_cn:tutorial:screenhandler [2022/12/09 04:51] – solidblock | zh_cn:tutorial:screenhandler [2024/08/27 04:50] (current) – update translations solidblock | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== 创建一个容器方块 ====== | + | ====== 创建容器方块 ====== |
| 这篇教程会创建一个类似发射器的简单存储方块,并解释如何使用 Fabric 和原版 Minecraft 中的 ScreenHandler API 构建用户界面。 | 这篇教程会创建一个类似发射器的简单存储方块,并解释如何使用 Fabric 和原版 Minecraft 中的 ScreenHandler API 构建用户界面。 | ||
| 先解释一些词汇: | 先解释一些词汇: | ||
| - | **Screenhandler:** | + | **Screenhandler:** |
| '' | '' | ||
| - | **Screen:** | + | **Screen:** |
| '' | '' | ||
| Line 18: | Line 18: | ||
| protected BoxBlock(Settings settings) { | protected BoxBlock(Settings settings) { | ||
| super(settings); | super(settings); | ||
| + | } | ||
| + | | ||
| + | // 从 1.20.5 开始需要有这个方法。 | ||
| + | @Override | ||
| + | protected MapCodec<? | ||
| + | return createCodec(BoxBlock:: | ||
| } | } | ||
| Line 106: | Line 112: | ||
| public Text getDisplayName() { | public Text getDisplayName() { | ||
| return Text.translatable(getCachedState().getBlock().getTranslationKey()); | return Text.translatable(getCachedState().getBlock().getTranslationKey()); | ||
| - | // 对于1.19之前的版本,请使用: | + | // 对于 1.19 之前的版本,请使用: |
| // return new TranslatableText(getCachedState().getBlock().getTranslationKey()); | // return new TranslatableText(getCachedState().getBlock().getTranslationKey()); | ||
| } | } | ||
| | | ||
| + | // 以下两个方法,旧版本请移除参数 `registryLookup`。 | ||
| @Override | @Override | ||
| - | public void readNbt(NbtCompound nbt) { | + | public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { |
| - | super.readNbt(nbt); | + | super.readNbt(nbt, registryLookup); |
| - | Inventories.readNbt(nbt, | + | Inventories.readNbt(nbt, |
| } | } | ||
| @Override | @Override | ||
| - | public NbtCompound writeNbt(NbtCompound nbt) { | + | public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { |
| - | super.writeNbt(nbt); | + | super.writeNbt(nbt, registryLookup); |
| - | Inventories.writeNbt(nbt, | + | Inventories.writeNbt(nbt, |
| return nbt; | return nbt; | ||
| } | } | ||
| Line 127: | Line 134: | ||
| ===== 注册方块、物品和方块实体 ===== | ===== 注册方块、物品和方块实体 ===== | ||
| + | 在这个例子中,方块、方块物品。方块实体直接注册在 '' | ||
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| public class ExampleMod implements ModInitializer { | public class ExampleMod implements ModInitializer { | ||
| - | | + | // 对于 1.21 之前的版本,将 `Identifier.of` 替换为 `new Identifier`。 |
| - | public static final BlockItem BOX_BLOCK_ITEM; | + | |
| - | public static final BlockEntityType< | + | |
| - | + | | |
| - | public static final String MOD_ID = " | + | public static final BlockItem |
| - | | + | |
| - | public static final Identifier | + | |
| - | + | | |
| - | static | + | |
| - | | + | // 在 1.17 使用 FabricBlockEntityTypeBuilder 而不是 BlockEntityType.Builder |
| - | BOX_BLOCK_ITEM = Registry.register(Registry.ITEM, | + | // public static final BlockEntityType< |
| - | + | // FabricBlockEntityTypeBuilder.create(BoxBlockEntity:: | |
| - | | + | |
| - | // 1.17 之前 | + | |
| - | BOX_BLOCK_ENTITY = Registry.register(Registry.BLOCK_ENTITY_TYPE, | + | |
| - | // 在 1.17 使用 FabricBlockEntityTypeBuilder 而不是 BlockEntityType.Builder | + | |
| - | BOX_BLOCK_ENTITY = Registry.register(Registry.BLOCK_ENTITY_TYPE, | + | |
| - | } | + | |
| @Override | @Override | ||
| public void onInitialize() { | public void onInitialize() { | ||
| - | |||
| } | } | ||
| } | } | ||
| - | |||
| - | |||
| </ | </ | ||
| Line 174: | Line 173: | ||
| } | } | ||
| - | // 这个构造器是在服务器的 BlockEntity 中被调用的,无需线调用其他构造器,服务器知道容器的物品栏 | + | // 这个构造器是在服务器的 BlockEntity 中被调用的,无需先调用其他构造器,服务器知道容器的物品栏 |
| // 并直接将其作为参数传入。然后物品栏在客户端完成同步。 | // 并直接将其作为参数传入。然后物品栏在客户端完成同步。 | ||
| public BoxScreenHandler(int syncId, PlayerInventory playerInventory, | public BoxScreenHandler(int syncId, PlayerInventory playerInventory, | ||
| Line 184: | Line 183: | ||
| // 这会将槽位放置在 3×3 网格的正确位置中。这些槽位在客户端和服务器中都存在! | // 这会将槽位放置在 3×3 网格的正确位置中。这些槽位在客户端和服务器中都存在! | ||
| - | // 但是这不会渲染槽位的背景,这是 Screens | + | // 但是这不会渲染槽位的背景,这是 Screens |
| int m; | int m; | ||
| int l; | int l; | ||
| Line 243: | Line 242: | ||
| public class BoxScreen extends HandledScreen< | public class BoxScreen extends HandledScreen< | ||
| // GUI 纹理的路径,本例中使用发射器中的纹理 | // GUI 纹理的路径,本例中使用发射器中的纹理 | ||
| - | private static final Identifier TEXTURE = new Identifier(" | + | private static final Identifier TEXTURE = Identifier.ofVanilla(" |
| public BoxScreen(ScreenHandler handler, PlayerInventory inventory, Text title) { | public BoxScreen(ScreenHandler handler, PlayerInventory inventory, Text title) { | ||
| Line 250: | Line 249: | ||
| @Override | @Override | ||
| - | protected void drawBackground(MatrixStack matrices, float delta, int mouseX, int mouseY) { | + | protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) { |
| - | RenderSystem.setShader(GameRenderer:: | + | RenderSystem.setShader(GameRenderer:: |
| RenderSystem.setShaderColor(1.0F, | RenderSystem.setShaderColor(1.0F, | ||
| RenderSystem.setShaderTexture(0, | RenderSystem.setShaderTexture(0, | ||
| int x = (width - backgroundWidth) / 2; | int x = (width - backgroundWidth) / 2; | ||
| int y = (height - backgroundHeight) / 2; | int y = (height - backgroundHeight) / 2; | ||
| - | drawTexture(matrices, x, y, 0, 0, backgroundWidth, | + | |
| } | } | ||
| @Override | @Override | ||
| - | public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { | + | public void render(DrawContext context, int mouseX, int mouseY, float delta) { |
| - | renderBackground(matrices); | + | renderBackground(context, mouseX, mouseY, delta); |
| - | super.render(matrices, mouseX, mouseY, delta); | + | super.render(context, mouseX, mouseY, delta); |
| - | drawMouseoverTooltip(matrices, mouseX, mouseY); | + | drawMouseoverTooltip(context, mouseX, mouseY); |
| } | } | ||
| Line 280: | Line 279: | ||
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| - | |||
| @Environment(EnvType.CLIENT) | @Environment(EnvType.CLIENT) | ||
| public class ExampleClientMod implements ClientModInitializer { | public class ExampleClientMod implements ClientModInitializer { | ||
| @Override | @Override | ||
| public void onInitializeClient() { | public void onInitializeClient() { | ||
| - | | + | |
| } | } | ||
| } | } | ||
| Line 292: | Line 290: | ||
| 别忘了在 '' | 别忘了在 '' | ||
| - | <code json> | + | < |
| - | /* ... */ | + | { |
| + | /* ... */ | ||
| " | " | ||
| /* ... */ | /* ... */ | ||
| " | " | ||
| - | "(到这个 | + | "net.fabricmc.example.ExampleModClient" |
| ] | ] | ||
| }, | }, | ||
| + | /* ... */ | ||
| + | } | ||
| </ | </ | ||
| Line 307: | Line 308: | ||
| public class ExampleMod implements ModInitializer { | public class ExampleMod implements ModInitializer { | ||
| [...] | [...] | ||
| - | public static final ScreenHandlerType< | + | public static final ScreenHandlerType< |
| - | [...] | + | |
| - | static { | + | |
| - | [...] | + | |
| - | // 我们在这里使用 registerSimple 因为实体不是 ExtendedScreenHandlerFactory | + | |
| - | // 而是 NamedScreenHandlerFactory. | + | |
| - | // 后面的教程中,你将会看到 ExtendedScreenHandlerFactory 能做什么! | + | |
| - | BOX_SCREEN_HANDLER = ScreenHandlerRegistry.registerSimple(BOX, BoxScreenHandler:: | + | |
| - | | + | |
| @Override | @Override | ||
| public void onInitialize() { | public void onInitialize() { | ||
| + | [...] | ||
| } | } | ||
| } | } | ||
| Line 330: | Line 323: | ||
| ===== 延伸阅读 ===== | ===== 延伸阅读 ===== | ||
| - | - [[extendedscreenhandler|屏幕开启时,使用 Extended ScreenHandlers 同步自定义的数据]] | + | * [[extendedscreenhandler|屏幕开启时,使用 Extended ScreenHandlers 同步自定义的数据]] |
| - | + | | |
| - | - [[propertydelegates|使用 PropertyDelegates 持续同步整数]] | + | |
| - | - 使用 '' | + | 使用 '' |
zh_cn/tutorial/screenhandler.1670561465.txt.gz · Last modified: 2022/12/09 04:51 by solidblock