Skip to content

Client Sided Guis

Juuz edited this page Jul 23, 2024 · 13 revisions

If you're writing a config panel, an instruction book, or any other non-inventory gui, it's often easier to have nothing to do with HandledScreen. That's where CottonClientScreen comes in.

If you prefer to watch a video tutorial. There is one available on YouTube for Minecraft 1.15: https://www.youtube.com/watch?v=WZbKcQ6B12I

To set up a clientside cotton gui, we will:

  • Make a subclass of CottonClientScreen - you probably won't modify your subclass at all, but it helps people writing addons to your mod target your gui specifically.
  • Make a subclass of LightweightGuiDescription - this is the heart of your gui. You'll add all your widgets and painters to this.
  • Ask minecraft to open your gui

Subclassing CottonClientScreen

package com.examplemod;

import io.github.cottonmc.cotton.gui.GuiDescription;
import io.github.cottonmc.cotton.gui.client.CottonClientScreen;

/**
 * This subclass doesn't need to do anything, just be a distinct
 * class so that anyone making edits or adding buttons can find us
 * with an instanceof check
 */
public class ExampleScreen extends CottonClientScreen {
    public ExampleScreen(GuiDescription description) {
        super(description);
    }
}

Subclassing LightweightGuiDescription

public class ExampleGui extends LightweightGuiDescription {
    public ExampleGui() {
        WGridPanel root = new WGridPanel();
        setRootPanel(root);
        root.setSize(256, 240);
        root.setInsets(Insets.ROOT_PANEL);
        
        WSprite icon = new WSprite(Identifier.ofVanilla("textures/item/redstone.png"));
        root.add(icon, 0, 2, 1, 1);
        
        WButton button = new WButton(Text.translatable("gui.examplemod.examplebutton"));
        root.add(button, 0, 3, 4, 1);
        
        WLabel label = new WLabel(Text.literal("Test"), 0xFFFFFF);
        root.add(label, 0, 4, 2, 1);

        root.validate(this);
    }
}

As with other Cotton GUIs, your GUI is made of a component hierarchy of different kinds of WPanels and WWidgets. You can nest panels of different kinds to any depth in order to organize and position components. The default root panel is a WGridPanel, which positions its components on an itemslot-sized (18-pixel) grid. You can use WPlainPanel in order to position and size components by pixels instead. Keep in mind that some components have no intrinsic size, so you probably want to use the five-argument add(WWidget widget, int x, int y, int width, int height) method for plain panels.

WWidgets can be subclassed and remixed into extremely custom controls. There are several drawing methods in ScreenDrawing to help out with this.

Opening Your Gui

Assuming your ClientCottonScreen subclass is called ExampleScreen, and your LightweightGuiDescription is called ExampleGui, the process to open your gui is pretty simple. Only do this once you're sure you're only running on the client.

MinecraftClient.getInstance().setScreen(new ExampleScreen(new ExampleGui()));

or, if you elect not to subclass CottonClientScreen, the following will also work:

MinecraftClient.getInstance().setScreen(new CottonClientScreen(new ExampleGui()));

That's it. No ScreenHandlerType, no packets, just be absolutely certain to only do this on the client. You can't call MinecraftClient.setScreen directly from common methods like Block.onUse, Item.use or Item.useOnBlock - then you need packets or a SyncedGuiDescription.

Next steps

(coming soon: How to add your CottonClientScreen as a modmenu settings gui)