aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/GuiItem.java45
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java10
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/TestItemDescription.java156
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java6
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/client/PaddingTestGui.java7
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/ItemSyncedGuiDescription.java63
6 files changed, 271 insertions, 16 deletions
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/GuiItem.java b/GuiTest/src/main/java/io/github/cottonmc/test/GuiItem.java
index 4fbc6df..27c8d5f 100644
--- a/GuiTest/src/main/java/io/github/cottonmc/test/GuiItem.java
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/GuiItem.java
@@ -1,20 +1,23 @@
package io.github.cottonmc.test;
-import net.fabricmc.api.EnvType;
-import net.fabricmc.api.Environment;
-import net.minecraft.client.MinecraftClient;
+import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
+import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.StackReference;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
+import net.minecraft.network.PacketByteBuf;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.server.network.ServerPlayerEntity;
+import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Rarity;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
-import io.github.cottonmc.cotton.gui.client.CottonClientScreen;
-import io.github.cottonmc.test.client.TestClientGui;
-
public class GuiItem extends Item {
public GuiItem() {
super(new Item.Settings().rarity(Rarity.EPIC));
@@ -22,15 +25,31 @@ public class GuiItem extends Item {
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
- if (world.isClient) {
- openScreen(); // In its own method to prevent class loading issues
- }
-
+ player.openHandledScreen(createScreenHandlerFactory(player, hand));
return new TypedActionResult<>(ActionResult.SUCCESS, player.getStackInHand(hand));
}
- @Environment(EnvType.CLIENT)
- private void openScreen() {
- MinecraftClient.getInstance().setScreen(new CottonClientScreen(new TestClientGui()));
+ private NamedScreenHandlerFactory createScreenHandlerFactory(PlayerEntity player, Hand hand) {
+ EquipmentSlot slot = switch (hand) {
+ case MAIN_HAND -> EquipmentSlot.MAINHAND;
+ case OFF_HAND -> EquipmentSlot.OFFHAND;
+ };
+ ItemStack stack = player.getStackInHand(hand);
+ return new ExtendedScreenHandlerFactory() {
+ @Override
+ public Text getDisplayName() {
+ return stack.getName();
+ }
+
+ @Override
+ public ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) {
+ return new TestItemDescription(syncId, playerInventory, StackReference.of(player, slot));
+ }
+
+ @Override
+ public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf) {
+ buf.writeEnumConstant(slot);
+ }
+ };
}
}
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java b/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java
index 3c11004..1d48daa 100644
--- a/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java
@@ -2,13 +2,16 @@ package io.github.cottonmc.test;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
+import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntityType;
+import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.StackReference;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
@@ -32,6 +35,7 @@ public class LibGuiTest implements ModInitializer {
public static BlockItem GUI_BLOCK_ITEM;
public static BlockEntityType<GuiBlockEntity> GUI_BLOCKENTITY_TYPE;
public static ScreenHandlerType<TestDescription> GUI_SCREEN_HANDLER_TYPE;
+ public static ScreenHandlerType<TestItemDescription> ITEM_SCREEN_HANDLER_TYPE;
public static ScreenHandlerType<ReallySimpleDescription> REALLY_SIMPLE_SCREEN_HANDLER_TYPE;
@Override
@@ -52,6 +56,12 @@ public class LibGuiTest implements ModInitializer {
return new TestDescription(GUI_SCREEN_HANDLER_TYPE, syncId, inventory, ScreenHandlerContext.EMPTY);
}, FeatureSet.of(FeatureFlags.VANILLA));
Registry.register(Registries.SCREEN_HANDLER, new Identifier(MODID, "gui"), GUI_SCREEN_HANDLER_TYPE);
+ ITEM_SCREEN_HANDLER_TYPE = new ExtendedScreenHandlerType<>((syncId, inventory, buf) -> {
+ var equipmentSlot = buf.readEnumConstant(EquipmentSlot.class);
+ StackReference handStack = StackReference.of(inventory.player, equipmentSlot);
+ return new TestItemDescription(syncId, inventory, handStack);
+ });
+ Registry.register(Registries.SCREEN_HANDLER, new Identifier(MODID, "item_gui"), ITEM_SCREEN_HANDLER_TYPE);
REALLY_SIMPLE_SCREEN_HANDLER_TYPE = new ScreenHandlerType<>(ReallySimpleDescription::new, FeatureSet.of(FeatureFlags.VANILLA));
Registry.register(Registries.SCREEN_HANDLER, new Identifier(MODID, "really_simple"), REALLY_SIMPLE_SCREEN_HANDLER_TYPE);
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/TestItemDescription.java b/GuiTest/src/main/java/io/github/cottonmc/test/TestItemDescription.java
new file mode 100644
index 0000000..4c9c1f0
--- /dev/null
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/TestItemDescription.java
@@ -0,0 +1,156 @@
+package io.github.cottonmc.test;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.StackReference;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+import io.github.cottonmc.cotton.gui.ItemSyncedGuiDescription;
+import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
+import io.github.cottonmc.cotton.gui.widget.TooltipBuilder;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WLabel;
+import io.github.cottonmc.cotton.gui.widget.WSlider;
+import io.github.cottonmc.cotton.gui.widget.WTextField;
+import io.github.cottonmc.cotton.gui.widget.WTiledSprite;
+import io.github.cottonmc.cotton.gui.widget.WWidget;
+import io.github.cottonmc.cotton.gui.widget.data.Axis;
+import io.github.cottonmc.cotton.gui.widget.data.Color;
+import io.github.cottonmc.cotton.gui.widget.data.Insets;
+
+public class TestItemDescription extends ItemSyncedGuiDescription {
+ private int r = 0;
+ private int g = 0;
+ private int b = 0;
+
+ public TestItemDescription(int syncId, PlayerInventory playerInventory, StackReference owner) {
+ super(LibGuiTest.ITEM_SCREEN_HANDLER_TYPE, syncId, playerInventory, owner);
+ WGridPanel root = new WGridPanel(22);
+ root.setInsets(Insets.ROOT_PANEL);
+ this.setRootPanel(root);
+ WLabel title = new WLabel(Text.literal("Client Test Gui"), WLabel.DEFAULT_TEXT_COLOR) {
+ @Environment(EnvType.CLIENT)
+ @Override
+ public void addTooltip(TooltipBuilder tooltip) {
+ tooltip.add(Text.literal("Radical!"));
+ }
+ };
+ WTiledSprite wood = new WTiledSprite(
+ 8, 8, // tile width and height
+ 500, // animation speed
+ new Identifier("minecraft:textures/block/birch_planks.png"),
+ new Identifier("minecraft:textures/block/dark_oak_planks.png"),
+ new Identifier("minecraft:textures/block/jungle_planks.png")
+ );
+ root.add(wood, 3, 3, 2, 2);
+ root.add(title, 0, 0);
+
+ WTextField text = new WTextField();
+ text.setSuggestion(Text.literal("Search"));
+ root.add(text, 0, 1, 8, 1);
+ text.setSize(7*18, 20);
+ /*
+ ArrayList<String> data = new ArrayList<>();
+ data.add("Wolfram Alpha");
+ data.add("Strange Home");
+ data.add("Nether Base");
+ data.add("Death");
+ data.add("Cake");
+ data.add("Mushroom Island");
+ data.add("A List Item");
+ data.add("Notes");
+ data.add("Slime Island");
+
+ BiConsumer<String, PortalDestination> configurator = (String s, PortalDestination destination) -> {
+ destination.label.setText(new LiteralText(s));
+
+ int hash = s.hashCode();
+ Identifier sprite = ((hash & 0x01) == 0) ? PORTAL1 : PORTAL2;
+ destination.sprite.setImage(sprite);
+
+ int cost = (hash >> 1) & 0x2FF;
+ destination.cost.setText(new LiteralText(""+cost+" XP"));
+ };
+ WListPanel<String, PortalDestination> list = new WListPanel<String, PortalDestination>(data, PortalDestination.class, PortalDestination::new, configurator);
+ list.setListItemHeight(2*18);
+ list.setBackgroundPainter(PANEL);
+ root.add(list, 0, 2, 7, 6);
+
+ root.add(new WButton(new LiteralText("Teleport")), 3,8,4,1);*/
+ WColorBox col = new WColorBox();
+ root.add(col, 3,2,1,3);
+
+ WSlider r = new WSlider(0, 100, Axis.VERTICAL);
+ root.add(r, 0, 2, 1, 3);
+ r.setValueChangeListener((i)->{
+ this.r = i;
+ updateCol(col);
+ System.out.println("h: "+this.r+" s: "+this.g+ " l: "+this.b);
+ System.out.println("col is now "+Integer.toHexString(col.color));
+ });
+ WSlider g = new WSlider(0, 100, Axis.VERTICAL);
+ root.add(g, 1, 2, 1, 3);
+ g.setValueChangeListener((i)->{
+ this.g = i;
+ updateCol(col);
+ });
+ WSlider b = new WSlider(0, 100, Axis.VERTICAL);
+ root.add(b, 2, 2, 1, 3);
+ b.setValueChangeListener((i)->{
+ this.b = i;
+ updateCol(col);
+ });
+
+ root.validate(this);
+ }
+ /*
+ public static class PortalDestination extends WPlainPanel {
+ WSprite sprite;
+ WLabel label;
+ WLabel cost;
+
+ public PortalDestination() {
+ sprite = new WSprite(new Identifier("libgui-test:portal"));
+ this.add(sprite, 2, 2, 18, 18);
+ label = new WLabel("Foo");
+ this.add(label, 18+ 4, 2, 5*18, 18);
+ cost = new WLabel("1000 Xp");
+ this.add(cost, 2, 20, 6*18, 18);
+
+ this.setSize(7*18, 2*18);
+
+ this.setBackgroundPainter(PANEL); //Would fail on a serverside gui
+ }
+ }*/
+
+ private void updateCol(WColorBox col) {
+ Color.HSL hsl = new Color.HSL(r/100f, g/100f, b/100f);
+ col.setColor(hsl.toRgb());
+ }
+
+ public static class WColorBox extends WWidget {
+ protected int color = 0xFF_FFFFFF;
+ public WColorBox() {}
+
+ public WColorBox(int col) {
+ this.color = col;
+ }
+
+ @Override
+ public boolean canResize() {
+ return true;
+ }
+
+ public void setColor(int col) {
+ this.color = col;
+ }
+
+ @Override
+ public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
+ ScreenDrawing.coloredRect(matrices, x, y, this.getWidth(), this.getHeight(), color);
+ }
+ }
+}
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java b/GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java
index 794264c..32e8343 100644
--- a/GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java
@@ -18,6 +18,7 @@ import io.github.cottonmc.cotton.gui.widget.WLabel;
import io.github.cottonmc.test.LibGuiTest;
import io.github.cottonmc.test.ReallySimpleDescription;
import io.github.cottonmc.test.TestDescription;
+import io.github.cottonmc.test.TestItemDescription;
import java.util.function.Function;
@@ -38,6 +39,11 @@ public class LibGuiTestClient implements ClientModInitializer {
CottonInventoryScreen::new
);
+ HandledScreens.<TestItemDescription, CottonInventoryScreen<TestItemDescription>>register(
+ LibGuiTest.ITEM_SCREEN_HANDLER_TYPE,
+ CottonInventoryScreen::new
+ );
+
CottonHud.add(new WHudTest(), 10, -20, 10, 10);
CottonHud.add(new WLabel(Text.literal("Test label")), 10, -30, 10, 10);
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/client/PaddingTestGui.java b/GuiTest/src/main/java/io/github/cottonmc/test/client/PaddingTestGui.java
index 367cab0..9f5d790 100644
--- a/GuiTest/src/main/java/io/github/cottonmc/test/client/PaddingTestGui.java
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/client/PaddingTestGui.java
@@ -1,13 +1,14 @@
package io.github.cottonmc.test.client;
+import net.minecraft.text.Text;
+
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
import io.github.cottonmc.cotton.gui.widget.WGridPanel;
import io.github.cottonmc.cotton.gui.widget.WLabel;
import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment;
import io.github.cottonmc.cotton.gui.widget.data.Insets;
import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment;
-
-import net.minecraft.text.Text;
+import io.github.cottonmc.test.TestItemDescription;
public class PaddingTestGui extends LightweightGuiDescription {
public PaddingTestGui(int hori, int vert) {
@@ -25,7 +26,7 @@ public class PaddingTestGui extends LightweightGuiDescription {
}
void addBox(WGridPanel root, int x, int y, int w, int h) {
- root.add(new TestClientGui.WColorBox(0xffff0000), x, y, w, h);
+ root.add(new TestItemDescription.WColorBox(0xffff0000), x, y, w, h);
var l = new WLabel(Text.literal(w + "x" + h), 0xff00ffff);
l.setVerticalAlignment(VerticalAlignment.CENTER);
l.setHorizontalAlignment(HorizontalAlignment.CENTER);
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/ItemSyncedGuiDescription.java b/src/main/java/io/github/cottonmc/cotton/gui/ItemSyncedGuiDescription.java
new file mode 100644
index 0000000..bdf3479
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/ItemSyncedGuiDescription.java
@@ -0,0 +1,63 @@
+package io.github.cottonmc.cotton.gui;
+
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.StackReference;
+import net.minecraft.item.ItemStack;
+import net.minecraft.screen.ScreenHandlerType;
+
+import java.util.Objects;
+
+/**
+ * A {@link SyncedGuiDescription} for an {@linkplain ItemStack item stack}
+ * in an {@linkplain net.minecraft.inventory.Inventory inventory}.
+ *
+ * <p>The owning item is represented with a {@link StackReference}, which can be
+ * an item in an entity's inventory or a block's container, or any other reference
+ * to an item stack.
+ *
+ * <p>If the owning item stack changes in any way, the screen closes by default (see {@link #canUse(PlayerEntity)}).
+ *
+ * @since 7.0.0
+ */
+public class ItemSyncedGuiDescription extends SyncedGuiDescription {
+ /**
+ * A reference to the owning item stack of this GUI.
+ */
+ protected final StackReference owner;
+
+ /**
+ * The initial item stack of this GUI. This stack must <strong>not</strong> be mutated!
+ */
+ protected final ItemStack ownerStack;
+
+ /**
+ * Constructs an {@code ItemSyncedGuiDescription}.
+ *
+ * @param type the screen handler type
+ * @param syncId the sync ID
+ * @param playerInventory the inventory of the player viewing this GUI description
+ * @param owner a reference to the owning item stack of this GUI description
+ */
+ public ItemSyncedGuiDescription(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory, StackReference owner) {
+ super(type, syncId, playerInventory);
+ this.owner = Objects.requireNonNull(owner, "Owner cannot be null");
+ this.ownerStack = owner.get().copy();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>The default implementation for {@code ItemSyncedGuiDescription} returns {@code true} if and only if
+ * the {@linkplain #owner current owning item stack} is {@linkplain ItemStack#areEqual fully equal}
+ * to the {@linkplain #ownerStack original owner}.
+ *
+ * <p>If the item NBT is intended to change, subclasses should override this method to only check
+ * the item and the count. Those subclasses should also take care to respond properly
+ * to any NBT changes in the owning item stack.
+ */
+ @Override
+ public boolean canUse(PlayerEntity entity) {
+ return ItemStack.areEqual(ownerStack, owner.get());
+ }
+}