mc-gui · v1.14.4 · 2026-08-27 · sha256 323f2567eabef360

mc-gui v1.14.4A

Immutable. This exact content is served forever at /api/v1/blob/323f2567eabef360.

---
name: mc-gui
description: Fabric 1.14.4 GUI。Container、ContainerType、ScreenProviderRegistry。触发词:GUI、Container、Screen、ScreenProviderRegistry
platform: fabric
version: "1.14.4"
dependencies: []
mappings: yarn
---

# GUI 开发(Fabric 1.14.4)

1.14.x Yarn 服务端菜单是 `Container` / `ContainerType` / `Registry.CONTAINER`。
客户端用 `ScreenProviderRegistry`,打开用 `ContainerProviderRegistry`。
不要抄 1.16+ 的 `ScreenHandler` / `HandledScreens` / `NamedScreenHandlerFactory` / `ButtonWidget.builder` / `Text.literal`。
不要写 `net.fabric.sdk`。

Yarn 已核:`Container(ContainerType, int)`、`Screen(Text)`、`ButtonWidget(..., String, PressAction)`、`transferSlot`。

## 快速开始

```java
public class MyContainer extends Container {
    public MyContainer(int syncId, PlayerInventory playerInventory) {
        super(MY_SCREEN, syncId);
        // addSlot(...):方块槽 + 玩家物品栏
    }

    @Override
    public boolean canUse(PlayerEntity player) {
        return true;
    }

    @Override
    public ItemStack transferSlot(PlayerEntity player, int invSlot) {
        return ItemStack.EMPTY;
    }
}

public static final Identifier MY_SCREEN_ID = new Identifier(MOD_ID, "my_screen");

public static final ContainerType<MyContainer> MY_SCREEN = Registry.register(
    Registry.CONTAINER,
    MY_SCREEN_ID,
    new ContainerType<>(MyContainer::new)
);
```

客户端注册与按钮:

```java
public class ExampleModClient implements ClientModInitializer {
    @Override
    public void onInitializeClient() {
        ScreenProviderRegistry.INSTANCE.registerFactory(
            MY_SCREEN_ID,
            (ContainerScreenFactory<MyContainer>) container ->
                new MyScreen(new TranslatableText("gui.examplemod.my_screen"))
        );
    }
}

public class MyScreen extends Screen {
    public MyScreen(Text title) {
        super(title);
    }

    @Override
    protected void init() {
        addButton(new ButtonWidget(width / 2 - 50, height / 2, 100, 20,
            "OK", btn -> this.minecraft.openScreen(null)));
    }
}
```

服务端打开(同一 Identifier;工厂签名已核 loader-api):

```java
ContainerProviderRegistry.INSTANCE.registerFactory(
    MY_SCREEN_ID,
    (syncId, identifier, player, buf) -> new MyContainer(syncId, player.inventory));

ContainerProviderRegistry.INSTANCE.openContainer(
    MY_SCREEN_ID, (ServerPlayerEntity) player, buf -> {});
```

## Decision: 选择 GUI 类型

```
IF 简单界面(按钮、文本)
  → Screen + TextFieldWidget + addButton(ButtonWidget 构造函数)

IF 容器型界面(箱子、机器)
  → Container + ScreenProviderRegistry + ContainerProviderRegistry

IF 需要同步额外数据
  → openContainer 的 PacketByteBuf writer(不要编造 TypedScreenHandlerFactory)
```

## 常见错误

- ❌ 在 `onInitialize()` 里注册客户端 Screen — 专用服务端崩溃,应在 `ClientModInitializer`
- ❌ 在 Screen 里直接改服务端库存 — 通过 Container 槽位同步
- ❌ 忘记 `super.render()` — 背景和子控件不渲染
- ❌ 用 `HandledScreens` / `ScreenHandler` / `Text.literal` / `ButtonWidget.builder` — 都不是本档 API
- ❌ `MatrixStack` 版 `render` — 1.14.4 的 `render` 没有 MatrixStack 参数
- ❌ `super()` / `super(null, syncId)` — Yarn 是 `Container(ContainerType, int)`
- ❌ 抄 wiki 现页 `quickMove` — 本档 Yarn 名是 `transferSlot`

## 扩展点

| 配合 Skill | 协作说明 |
|-----------|---------|
| `mc-registry` | `ContainerType` 用 `Registry.register(Registry.CONTAINER, ...)` |
| `mc-block` | 方块实体里调用 `ContainerProviderRegistry.openContainer` |
| `mc-networking` | 槽位不够时再发自定义包 |