diff options
41 files changed, 1247 insertions, 208 deletions
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlock.java b/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlock.java index ded6fcb..69a0640 100644 --- a/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlock.java +++ b/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlock.java @@ -1,38 +1,35 @@ package io.github.cottonmc.test; -import net.fabricmc.fabric.api.block.FabricBlockSettings; -import net.fabricmc.fabric.api.container.ContainerProviderRegistry; -import net.minecraft.block.Block; -import net.minecraft.block.BlockEntityProvider; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.minecraft.block.*; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.BlockView; import net.minecraft.world.World; -public class GuiBlock extends Block implements BlockEntityProvider { +public class GuiBlock extends BlockWithEntity { public GuiBlock() { - super(FabricBlockSettings.copy(Blocks.IRON_BLOCK).build()); + super(FabricBlockSettings.copy(Blocks.IRON_BLOCK)); } @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hitResult) { - if (!world.isClient) { - ContainerProviderRegistry.INSTANCE.openContainer(new Identifier(LibGuiTest.MODID, "gui"), player, (buf)->buf.writeBlockPos(pos)); - } + player.openHandledScreen(state.createScreenHandlerFactory(world, pos)); return ActionResult.SUCCESS; } - @Override public BlockEntity createBlockEntity(BlockView var1) { return new GuiBlockEntity(); } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } } diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlockEntity.java b/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlockEntity.java index 3e76fdd..c699b47 100644 --- a/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlockEntity.java +++ b/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlockEntity.java @@ -2,10 +2,18 @@ package io.github.cottonmc.test; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.ScreenHandlerContext; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; import net.minecraft.util.collection.DefaultedList; -public class GuiBlockEntity extends BlockEntity implements ImplementedInventory { +import javax.annotation.Nullable; + +public class GuiBlockEntity extends BlockEntity implements ImplementedInventory, NamedScreenHandlerFactory { DefaultedList<ItemStack> items = DefaultedList.ofSize(8, ItemStack.EMPTY); @@ -23,4 +31,14 @@ public class GuiBlockEntity extends BlockEntity implements ImplementedInventory return pos.isWithinDistance(player.getBlockPos(), 4.5); } + @Override + public Text getDisplayName() { + return new LiteralText(""); // no title + } + + @Nullable + @Override + public ScreenHandler createMenu(int syncId, PlayerInventory inv, PlayerEntity player) { + return new TestDescription(LibGuiTest.GUI_SCREEN_HANDLER_TYPE, syncId, inv, ScreenHandlerContext.create(world, pos)); + } } 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 b777361..699c38e 100644 --- a/GuiTest/src/main/java/io/github/cottonmc/test/GuiItem.java +++ b/GuiTest/src/main/java/io/github/cottonmc/test/GuiItem.java @@ -2,6 +2,8 @@ package io.github.cottonmc.test; import io.github.cottonmc.cotton.gui.client.CottonClientScreen; import io.github.cottonmc.test.client.TestClientGui; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; @@ -21,10 +23,15 @@ public class GuiItem extends Item { @Override public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) { - if (world.isClient) { - MinecraftClient.getInstance().openScreen(new CottonClientScreen(new TestClientGui())); + if (world.isClient) { + openScreen(); // In its own method to prevent class loading issues } return new TypedActionResult<ItemStack>(ActionResult.SUCCESS, (hand==Hand.MAIN_HAND) ? player.getMainHandStack() : player.getOffHandStack()); } + + @Environment(EnvType.CLIENT) + private void openScreen() { + MinecraftClient.getInstance().openScreen(new CottonClientScreen(new TestClientGui())); + } } 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 90f3c92..8b567b7 100644 --- a/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java +++ b/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java @@ -6,16 +6,16 @@ import java.nio.file.Path; import java.util.Optional; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.container.ContainerProviderRegistry; +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; -import net.minecraft.network.PacketByteBuf; import net.minecraft.screen.ScreenHandlerContext; +import net.minecraft.screen.ScreenHandlerType; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; @@ -25,6 +25,8 @@ public class LibGuiTest implements ModInitializer { public static GuiBlock GUI_BLOCK; public static BlockItem GUI_BLOCK_ITEM; public static BlockEntityType<GuiBlockEntity> GUI_BLOCKENTITY_TYPE; + public static ScreenHandlerType<TestDescription> GUI_SCREEN_HANDLER_TYPE; + @Override public void onInitialize() { Registry.register(Registry.ITEM, new Identifier(MODID, "client_gui"), new GuiItem()); @@ -36,11 +38,10 @@ public class LibGuiTest implements ModInitializer { GUI_BLOCKENTITY_TYPE = BlockEntityType.Builder.create(GuiBlockEntity::new, GUI_BLOCK).build(null); Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(MODID, "gui"), GUI_BLOCKENTITY_TYPE); - - ContainerProviderRegistry.INSTANCE.registerFactory(new Identifier(MODID, "gui"), (int syncId, Identifier identifier, PlayerEntity player, PacketByteBuf buf)->{ - return new TestDescription(syncId, player.inventory, ScreenHandlerContext.create(player.getEntityWorld(), buf.readBlockPos())); + GUI_SCREEN_HANDLER_TYPE = ScreenHandlerRegistry.registerSimple(new Identifier(MODID, "gui"), (int syncId, PlayerInventory inventory) -> { + return new TestDescription(GUI_SCREEN_HANDLER_TYPE, syncId, inventory, ScreenHandlerContext.EMPTY); }); - + Optional<ModContainer> containerOpt = FabricLoader.getInstance().getModContainer("jankson"); if (containerOpt.isPresent()) { ModContainer jankson = containerOpt.get(); diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/TestDescription.java b/GuiTest/src/main/java/io/github/cottonmc/test/TestDescription.java index 3d5e48c..732494e 100644 --- a/GuiTest/src/main/java/io/github/cottonmc/test/TestDescription.java +++ b/GuiTest/src/main/java/io/github/cottonmc/test/TestDescription.java @@ -4,12 +4,13 @@ import io.github.cottonmc.cotton.gui.SyncedGuiDescription; import io.github.cottonmc.cotton.gui.widget.*; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.screen.ScreenHandlerContext; +import net.minecraft.screen.ScreenHandlerType; import net.minecraft.text.LiteralText; public class TestDescription extends SyncedGuiDescription { - public TestDescription(int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) { - super(syncId, playerInventory, getBlockInventory(context), null); + public TestDescription(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) { + super(type, syncId, playerInventory, getBlockInventory(context), null); WGridPanel root = (WGridPanel)this.getRootPanel(); 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 f0d3f27..5ef61c2 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 @@ -4,15 +4,16 @@ import io.github.cottonmc.cotton.gui.client.CottonInventoryScreen; import io.github.cottonmc.test.LibGuiTest; import io.github.cottonmc.test.TestDescription; import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry; -import net.minecraft.screen.ScreenHandlerContext; -import net.minecraft.util.Identifier; +import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; public class LibGuiTestClient implements ClientModInitializer { @Override public void onInitializeClient() { - ScreenProviderRegistry.INSTANCE.registerFactory(new Identifier(LibGuiTest.MODID, "gui"), (syncId, identifier, player, buf)->new CottonInventoryScreen<TestDescription>(new TestDescription(syncId, player.inventory, ScreenHandlerContext.create(player.getEntityWorld(), buf.readBlockPos())), player)); + ScreenRegistry.<TestDescription, CottonInventoryScreen<TestDescription>>register( + LibGuiTest.GUI_SCREEN_HANDLER_TYPE, + (desc, inventory, title) -> new CottonInventoryScreen<>(desc, inventory.player, title) + ); } } diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/client/TestClientGui.java b/GuiTest/src/main/java/io/github/cottonmc/test/client/TestClientGui.java index 45426b4..bcc2584 100644 --- a/GuiTest/src/main/java/io/github/cottonmc/test/client/TestClientGui.java +++ b/GuiTest/src/main/java/io/github/cottonmc/test/client/TestClientGui.java @@ -17,7 +17,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; +import net.minecraft.text.StringRenderable; import net.minecraft.util.Identifier; public class TestClientGui extends LightweightGuiDescription { @@ -39,7 +39,7 @@ public class TestClientGui extends LightweightGuiDescription { this.setRootPanel(root); WLabel title = new WLabel(new LiteralText("Client Test Gui"), WLabel.DEFAULT_TEXT_COLOR) { @Override - public void addTooltip(List<Text> tooltip) { + public void addTooltip(List<StringRenderable> tooltip) { tooltip.add(new LiteralText("Radical!")); } }; diff --git a/gradle.properties b/gradle.properties index fc09dbd..f9f6502 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,16 +3,16 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use - minecraft_version=1.16-pre2 - yarn_mappings=1.16-pre2+build.1 - loader_version=0.8.7+build.201 + minecraft_version=1.16.1 + yarn_mappings=1.16.1+build.20 + loader_version=0.8.8+build.202 # Mod Properties - mod_version = 2.0.0-beta.1 + mod_version = 2.2.0 maven_group = io.github.cottonmc archives_base_name = LibGui # Dependencies - fabric_version=0.11.6+build.355-1.16 + fabric_version=0.13.1+build.370-1.16 jankson_version=3.0.0+j1.2.0 modmenu_version=1.11.8+build.13 diff --git a/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java b/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java index 0c31912..cf1226b 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java @@ -5,6 +5,7 @@ import javax.annotation.Nullable; import io.github.cottonmc.cotton.gui.impl.FocusHandler; import io.github.cottonmc.cotton.gui.widget.WPanel; import io.github.cottonmc.cotton.gui.widget.WWidget; +import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.screen.PropertyDelegate; @@ -23,8 +24,30 @@ public interface GuiDescription { public int getTitleColor(); public GuiDescription setRootPanel(WPanel panel); + + /** + * Sets the title color of this GUI. + * + * <p>The dark-mode title color will also be set by this method. + * If the specified color is {@link io.github.cottonmc.cotton.gui.widget.WLabel#DEFAULT_TEXT_COLOR}, + * the dark-mode color will be {@link io.github.cottonmc.cotton.gui.widget.WLabel#DEFAULT_DARKMODE_TEXT_COLOR}; + * otherwise it will be the specified color. + * + * @param color the new title color + * @return this GUI + */ public GuiDescription setTitleColor(int color); - + + /** + * Sets the light and dark title colors of this GUI. + * + * @param lightColor the light-mode color + * @param darkColor the dark-mode color + * @return this GUI + * @since 2.1.0 + */ + GuiDescription setTitleColor(int lightColor, int darkColor); + /** Sets the object which manages the integer properties used by WBars */ public GuiDescription setPropertyDelegate(PropertyDelegate delegate); @@ -61,4 +84,57 @@ public interface GuiDescription { default void cycleFocus(boolean lookForwards) { FocusHandler.cycleFocus(this, lookForwards); } + + /** + * Gets whether this GUI is fullscreen. + * + * <p>Fullscreen GUIs have no default background painter and + * have the root panel stretched to fit the entire screen on the client. + * + * @return true if this GUI is fullscreen, false otherwise + * @since 2.0.0 + */ + boolean isFullscreen(); + + /** + * Sets whether this GUI is fullscreen. + * + * @param fullscreen true if this GUI is fullscreen, false otherwise + * @since 2.0.0 + */ + void setFullscreen(boolean fullscreen); + + /** + * Gets whether the title of this GUI should be rendered by the screen. + * + * <p>Modders can disable this to render the title themselves with a widget. + * + * @return true if the title is visible, false otherwise + * @since 2.0.0 + */ + boolean isTitleVisible(); + + /** + * Sets whether the title of this GUI should be rendered by the screen. + * + * @param titleVisible true if the title is visible, false otherwise + * @since 2.0.0 + */ + void setTitleVisible(boolean titleVisible); + + /** + * Gets the horizontal alignment of the GUI title. + * + * @return the alignment + * @since 2.1.0 + */ + HorizontalAlignment getTitleAlignment(); + + /** + * Sets the horizontal alignment of the GUI title. + * + * @param alignment the new alignment + * @since 2.1.0 + */ + void setTitleAlignment(HorizontalAlignment alignment); } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java b/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java index 5f2bef0..cd47af4 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java @@ -1,12 +1,14 @@ package io.github.cottonmc.cotton.gui; import java.util.ArrayList; +import java.util.function.Supplier; import javax.annotation.Nullable; import io.github.cottonmc.cotton.gui.client.BackgroundPainter; import io.github.cottonmc.cotton.gui.client.LibGuiClient; import io.github.cottonmc.cotton.gui.widget.*; +import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.block.Block; @@ -16,6 +18,7 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SimpleInventory; import net.minecraft.item.ItemStack; import net.minecraft.screen.*; import net.minecraft.screen.slot.Slot; @@ -35,19 +38,22 @@ public class SyncedGuiDescription extends ScreenHandler implements GuiDescriptio protected WPanel rootPanel = new WGridPanel(); protected int titleColor = WLabel.DEFAULT_TEXT_COLOR; protected int darkTitleColor = WLabel.DEFAULT_DARKMODE_TEXT_COLOR; - + protected boolean fullscreen = false; + protected boolean titleVisible = true; + protected HorizontalAlignment titleAlignment = HorizontalAlignment.LEFT; + protected WWidget focus; - - public SyncedGuiDescription(int syncId, PlayerInventory playerInventory) { - super(null, syncId); + + public SyncedGuiDescription(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory) { + super(type, syncId); this.blockInventory = null; this.playerInventory = playerInventory; this.world = playerInventory.player.world; this.propertyDelegate = null;//new ArrayPropertyDelegate(1); } - public SyncedGuiDescription(int syncId, PlayerInventory playerInventory, Inventory blockInventory, PropertyDelegate propertyDelegate) { - super(null, syncId); + public SyncedGuiDescription(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory, Inventory blockInventory, PropertyDelegate propertyDelegate) { + super(type, syncId); this.blockInventory = blockInventory; this.playerInventory = playerInventory; this.world = playerInventory.player.world; @@ -60,22 +66,31 @@ public class SyncedGuiDescription extends ScreenHandler implements GuiDescriptio } public int getTitleColor() { - return LibGuiClient.config.darkMode ? darkTitleColor : titleColor; + return (world.isClient && LibGuiClient.config.darkMode) ? darkTitleColor : titleColor; } public SyncedGuiDescription setRootPanel(WPanel panel) { this.rootPanel = panel; return this; } - + + @Override public SyncedGuiDescription setTitleColor(int color) { this.titleColor = color; + this.darkTitleColor = (color == WLabel.DEFAULT_TEXT_COLOR) ? WLabel.DEFAULT_DARKMODE_TEXT_COLOR : color; + return this; + } + + @Override + public SyncedGuiDescription setTitleColor(int lightColor, int darkColor) { + this.titleColor = lightColor; + this.darkTitleColor = darkColor; return this; } @Environment(EnvType.CLIENT) public void addPainters() { - if (this.rootPanel!=null) { + if (this.rootPanel!=null && !fullscreen) { this.rootPanel.setBackgroundPainter(BackgroundPainter.VANILLA); } } @@ -373,17 +388,43 @@ public class SyncedGuiDescription extends ScreenHandler implements GuiDescriptio * @return the found inventory */ public static Inventory getBlockInventory(ScreenHandlerContext ctx) { + return getBlockInventory(ctx, () -> EmptyInventory.INSTANCE); + } + + /** + * Gets the block inventory at the context. + * + * <p>If no inventory is found, returns a simple mutable inventory + * with the specified number of slots. + * + * <p>Searches for these implementations in the following order: + * <ol> + * <li>Blocks implementing {@code InventoryProvider}</li> + * <li>Block entities implementing {@code InventoryProvider}</li> + * <li>Block entities implementing {@code Inventory}</li> + * </ol> + * + * @param ctx the context + * @param size the fallback inventory size + * @return the found inventory + * @since 2.0.0 + */ + public static Inventory getBlockInventory(ScreenHandlerContext ctx, int size) { + return getBlockInventory(ctx, () -> new SimpleInventory(size)); + } + + private static Inventory getBlockInventory(ScreenHandlerContext ctx, Supplier<Inventory> fallback) { return ctx.run((world, pos) -> { BlockState state = world.getBlockState(pos); Block b = state.getBlock(); - + if (b instanceof InventoryProvider) { Inventory inventory = ((InventoryProvider)b).getInventory(state, world, pos); if (inventory != null) { return inventory; } } - + BlockEntity be = world.getBlockEntity(pos); if (be!=null) { if (be instanceof InventoryProvider) { @@ -395,9 +436,9 @@ public class SyncedGuiDescription extends ScreenHandler implements GuiDescriptio return (Inventory)be; } } - - return EmptyInventory.INSTANCE; - }).orElse(EmptyInventory.INSTANCE); + + return fallback.get(); + }).orElseGet(fallback); } /** @@ -420,6 +461,30 @@ public class SyncedGuiDescription extends ScreenHandler implements GuiDescriptio return new ArrayPropertyDelegate(0); }).orElse(new ArrayPropertyDelegate(0)); } + + /** + * Gets the property delegate at the context. + * + * <p>If no property delegate is found, returns an array property delegate + * with the specified number of properties. + * + * <p>Searches for block entities implementing {@link PropertyDelegateHolder}. + * + * @param ctx the context + * @param size the number of properties + * @return the found property delegate + * @since 2.0.0 + */ + public static PropertyDelegate getBlockPropertyDelegate(ScreenHandlerContext ctx, int size) { + return ctx.run((world, pos) -> { + BlockEntity be = world.getBlockEntity(pos); + if (be!=null && be instanceof PropertyDelegateHolder) { + return ((PropertyDelegateHolder)be).getPropertyDelegate(); + } + + return new ArrayPropertyDelegate(size); + }).orElse(new ArrayPropertyDelegate(size)); + } //extends ScreenHandler { @Override @@ -455,4 +520,34 @@ public class SyncedGuiDescription extends ScreenHandler implements GuiDescriptio widget.onFocusLost(); } } + + @Override + public boolean isFullscreen() { + return fullscreen; + |
