From ffa5a02e44381983ffdbddad0debc4569c1a1994 Mon Sep 17 00:00:00 2001 From: Juuxel <6596629+Juuxel@users.noreply.github.com> Date: Fri, 5 Jun 2020 18:01:27 +0300 Subject: CottonInventoryController -> SyncedGuiDescription --- .../java/io/github/cottonmc/test/LibGuiTest.java | 2 +- .../io/github/cottonmc/test/TestController.java | 30 -- .../io/github/cottonmc/test/TestDescription.java | 29 ++ .../cottonmc/test/client/LibGuiTestClient.java | 4 +- .../cotton/gui/CottonInventoryController.java | 458 --------------------- .../github/cottonmc/cotton/gui/GuiDescription.java | 2 +- .../cotton/gui/PropertyDelegateHolder.java | 2 +- .../cottonmc/cotton/gui/SyncedGuiDescription.java | 458 +++++++++++++++++++++ .../cotton/gui/client/CottonInventoryScreen.java | 10 +- 9 files changed, 497 insertions(+), 498 deletions(-) delete mode 100644 GuiTest/src/main/java/io/github/cottonmc/test/TestController.java create mode 100644 GuiTest/src/main/java/io/github/cottonmc/test/TestDescription.java delete mode 100644 src/main/java/io/github/cottonmc/cotton/gui/CottonInventoryController.java create mode 100644 src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java 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 6d63688..90f3c92 100644 --- a/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java +++ b/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java @@ -38,7 +38,7 @@ public class LibGuiTest implements ModInitializer { ContainerProviderRegistry.INSTANCE.registerFactory(new Identifier(MODID, "gui"), (int syncId, Identifier identifier, PlayerEntity player, PacketByteBuf buf)->{ - return new TestController(syncId, player.inventory, ScreenHandlerContext.create(player.getEntityWorld(), buf.readBlockPos())); + return new TestDescription(syncId, player.inventory, ScreenHandlerContext.create(player.getEntityWorld(), buf.readBlockPos())); }); Optional containerOpt = FabricLoader.getInstance().getModContainer("jankson"); diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/TestController.java b/GuiTest/src/main/java/io/github/cottonmc/test/TestController.java deleted file mode 100644 index 68905ef..0000000 --- a/GuiTest/src/main/java/io/github/cottonmc/test/TestController.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.cottonmc.test; - -import io.github.cottonmc.cotton.gui.CottonInventoryController; -import io.github.cottonmc.cotton.gui.widget.*; -import io.github.cottonmc.cotton.gui.widget.data.Axis; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.screen.ScreenHandlerContext; -import net.minecraft.text.LiteralText; - -public class TestController extends CottonInventoryController { - - public TestController(int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) { - super(syncId, playerInventory, getBlockInventory(context), null); - - WGridPanel root = (WGridPanel)this.getRootPanel(); - - root.add(WItemSlot.of(blockInventory, 0, 4, 1), 0, 1); - - root.add(new WButton(new LiteralText("Button A")), 0, 3, 4, 1); - root.add(new WButton(new LiteralText("Button B")), 5, 3, 4, 1); - root.add(new WButton(new LiteralText("Button C")), 0, 5, 4, 1); - root.add(new WButton(new LiteralText("Button D")), 5, 5, 4, 1); - root.add(new WTextField(new LiteralText("Type something...")), 0, 7, 5, 1); - - root.add(createPlayerInventoryPanel(), 0, 9); - System.out.println(root.toString()); - - this.getRootPanel().validate(this); - } -} diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/TestDescription.java b/GuiTest/src/main/java/io/github/cottonmc/test/TestDescription.java new file mode 100644 index 0000000..3d5e48c --- /dev/null +++ b/GuiTest/src/main/java/io/github/cottonmc/test/TestDescription.java @@ -0,0 +1,29 @@ +package io.github.cottonmc.test; + +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.text.LiteralText; + +public class TestDescription extends SyncedGuiDescription { + + public TestDescription(int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) { + super(syncId, playerInventory, getBlockInventory(context), null); + + WGridPanel root = (WGridPanel)this.getRootPanel(); + + root.add(WItemSlot.of(blockInventory, 0, 4, 1), 0, 1); + + root.add(new WButton(new LiteralText("Button A")), 0, 3, 4, 1); + root.add(new WButton(new LiteralText("Button B")), 5, 3, 4, 1); + root.add(new WButton(new LiteralText("Button C")), 0, 5, 4, 1); + root.add(new WButton(new LiteralText("Button D")), 5, 5, 4, 1); + root.add(new WTextField(new LiteralText("Type something...")), 0, 7, 5, 1); + + root.add(createPlayerInventoryPanel(), 0, 9); + System.out.println(root.toString()); + + this.getRootPanel().validate(this); + } +} 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 a2a23fb..f0d3f27 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 @@ -2,7 +2,7 @@ package io.github.cottonmc.test.client; import io.github.cottonmc.cotton.gui.client.CottonInventoryScreen; import io.github.cottonmc.test.LibGuiTest; -import io.github.cottonmc.test.TestController; +import io.github.cottonmc.test.TestDescription; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry; import net.minecraft.screen.ScreenHandlerContext; @@ -12,7 +12,7 @@ public class LibGuiTestClient implements ClientModInitializer { @Override public void onInitializeClient() { - ScreenProviderRegistry.INSTANCE.registerFactory(new Identifier(LibGuiTest.MODID, "gui"), (syncId, identifier, player, buf)->new CottonInventoryScreen(new TestController(syncId, player.inventory, ScreenHandlerContext.create(player.getEntityWorld(), buf.readBlockPos())), player)); + ScreenProviderRegistry.INSTANCE.registerFactory(new Identifier(LibGuiTest.MODID, "gui"), (syncId, identifier, player, buf)->new CottonInventoryScreen(new TestDescription(syncId, player.inventory, ScreenHandlerContext.create(player.getEntityWorld(), buf.readBlockPos())), player)); } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/CottonInventoryController.java b/src/main/java/io/github/cottonmc/cotton/gui/CottonInventoryController.java deleted file mode 100644 index 219f576..0000000 --- a/src/main/java/io/github/cottonmc/cotton/gui/CottonInventoryController.java +++ /dev/null @@ -1,458 +0,0 @@ -package io.github.cottonmc.cotton.gui; - -import java.util.ArrayList; - -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 net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.InventoryProvider; -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.item.ItemStack; -import net.minecraft.screen.*; -import net.minecraft.screen.slot.Slot; -import net.minecraft.screen.slot.SlotActionType; -import net.minecraft.world.World; - -/** - * A screen handler-based GUI description for GUIs with slots. - */ -public class CottonInventoryController extends ScreenHandler implements GuiDescription { - - protected Inventory blockInventory; - protected PlayerInventory playerInventory; - protected World world; - protected PropertyDelegate propertyDelegate; - - protected WPanel rootPanel = new WGridPanel(); - protected int titleColor = WLabel.DEFAULT_TEXT_COLOR; - protected int darkTitleColor = WLabel.DEFAULT_DARKMODE_TEXT_COLOR; - - protected WWidget focus; - - public CottonInventoryController(int syncId, PlayerInventory playerInventory) { - super(null, syncId); - this.blockInventory = null; - this.playerInventory = playerInventory; - this.world = playerInventory.player.world; - this.propertyDelegate = null;//new ArrayPropertyDelegate(1); - } - - public CottonInventoryController(int syncId, PlayerInventory playerInventory, Inventory blockInventory, PropertyDelegate propertyDelegate) { - super(null, syncId); - this.blockInventory = blockInventory; - this.playerInventory = playerInventory; - this.world = playerInventory.player.world; - this.propertyDelegate = propertyDelegate; - if (propertyDelegate!=null && propertyDelegate.size()>0) this.addProperties(propertyDelegate); - } - - public WPanel getRootPanel() { - return rootPanel; - } - - public int getTitleColor() { - return LibGuiClient.config.darkMode ? darkTitleColor : titleColor; - } - - public CottonInventoryController setRootPanel(WPanel panel) { - this.rootPanel = panel; - return this; - } - - public CottonInventoryController setTitleColor(int color) { - this.titleColor = color; - return this; - } - - @Environment(EnvType.CLIENT) - public void addPainters() { - if (this.rootPanel!=null) { - this.rootPanel.setBackgroundPainter(BackgroundPainter.VANILLA); - } - } - - public void addSlotPeer(ValidatedSlot slot) { - this.addSlot(slot); - } - - @Override - public ItemStack onSlotClick(int slotNumber, int button, SlotActionType action, PlayerEntity player) { - if (action==SlotActionType.QUICK_MOVE) { - - if (slotNumber < 0) { - return ItemStack.EMPTY; - } - - if (slotNumber>=this.slots.size()) return ItemStack.EMPTY; - Slot slot = this.slots.get(slotNumber); - if (slot == null || !slot.canTakeItems(player)) { - return ItemStack.EMPTY; - } - - ItemStack remaining = ItemStack.EMPTY; - if (slot != null && slot.hasStack()) { - ItemStack toTransfer = slot.getStack(); - remaining = toTransfer.copy(); - //if (slot.inventory==blockInventory) { - if (blockInventory!=null) { - if (slot.inventory==blockInventory) { - //Try to transfer the item from the block into the player's inventory - if (!this.insertItem(toTransfer, this.playerInventory, true, player)) { - return ItemStack.EMPTY; - } - } else if (!this.insertItem(toTransfer, this.blockInventory, false, player)) { //Try to transfer the item from the player to the block - return ItemStack.EMPTY; - } - } else { - //There's no block, just swap between the player's storage and their hotbar - if (!swapHotbar(toTransfer, slotNumber, this.playerInventory, player)) { - return ItemStack.EMPTY; - } - } - - if (toTransfer.isEmpty()) { - slot.setStack(ItemStack.EMPTY); - } else { - slot.markDirty(); - } - } - - return remaining; - } else { - return super.onSlotClick(slotNumber, button, action, player); - } - } - - /** WILL MODIFY toInsert! Returns true if anything was inserted. */ - private boolean insertIntoExisting(ItemStack toInsert, Slot slot, PlayerEntity player) { - ItemStack curSlotStack = slot.getStack(); - if (!curSlotStack.isEmpty() && canStacksCombine(toInsert, curSlotStack) && slot.canTakeItems(player)) { - int combinedAmount = curSlotStack.getCount() + toInsert.getCount(); - if (combinedAmount <= toInsert.getMaxCount()) { - toInsert.setCount(0); - curSlotStack.setCount(combinedAmount); - slot.markDirty(); - return true; - } else if (curSlotStack.getCount() < toInsert.getMaxCount()) { - toInsert.decrement(toInsert.getMaxCount() - curSlotStack.getCount()); - curSlotStack.setCount(toInsert.getMaxCount()); - slot.markDirty(); - return true; - } - } - return false; - } - - /** WILL MODIFY toInsert! Returns true if anything was inserted. */ - private boolean insertIntoEmpty(ItemStack toInsert, Slot slot) { - ItemStack curSlotStack = slot.getStack(); - if (curSlotStack.isEmpty() && slot.canInsert(toInsert)) { - if (toInsert.getCount() > slot.getMaxStackAmount()) { - slot.setStack(toInsert.split(slot.getMaxStackAmount())); - } else { - slot.setStack(toInsert.split(toInsert.getCount())); - } - - slot.markDirty(); - return true; - } - - return false; - } - - private boolean insertItem(ItemStack toInsert, Inventory inventory, boolean walkBackwards, PlayerEntity player) { - //Make a unified list of slots *only from this inventory* - ArrayList inventorySlots = new ArrayList<>(); - for(Slot slot : slots) { - if (slot.inventory==inventory) inventorySlots.add(slot); - } - if (inventorySlots.isEmpty()) return false; - - //Try to insert it on top of existing stacks - boolean inserted = false; - if (walkBackwards) { - for(int i=inventorySlots.size()-1; i>=0; i--) { - Slot curSlot = inventorySlots.get(i); - if (insertIntoExisting(toInsert, curSlot, player)) inserted = true; - if (toInsert.isEmpty()) break; - } - } else { - for(int i=0; i=0; i--) { - Slot curSlot = inventorySlots.get(i); - if (insertIntoEmpty(toInsert, curSlot)) inserted = true; - if (toInsert.isEmpty()) break; - } - } else { - for(int i=0; i storageSlots = new ArrayList<>(); - ArrayList hotbarSlots = new ArrayList<>(); - boolean swapToStorage = true; - boolean inserted = false; - - for(Slot slot : slots) { - if (slot.inventory==inventory && slot instanceof ValidatedSlot) { - int index = ((ValidatedSlot)slot).getInventoryIndex(); - if (PlayerInventory.isValidHotbarIndex(index)) { - hotbarSlots.add(slot); - } else { - storageSlots.add(slot); - if (index==slotNumber) swapToStorage = false; - } - } - } - if (storageSlots.isEmpty() || hotbarSlots.isEmpty()) return false; - - if (swapToStorage) { - //swap from hotbar to storage - for(int i=0; i=wx && x=wy && yIf no inventory is found, returns {@link EmptyInventory#INSTANCE}. - * - *

Searches for these implementations in the following order: - *

    - *
  1. Blocks implementing {@code InventoryProvider}
  2. - *
  3. Block entities implementing {@code InventoryProvider}
  4. - *
  5. Block entities implementing {@code Inventory}
  6. - *
- * - * @param ctx the context - * @return the found inventory - */ - public static Inventory getBlockInventory(ScreenHandlerContext ctx) { - 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) { - Inventory inventory = ((InventoryProvider)be).getInventory(state, world, pos); - if (inventory != null) { - return inventory; - } - } else if (be instanceof Inventory) { - return (Inventory)be; - } - } - - return EmptyInventory.INSTANCE; - }).orElse(EmptyInventory.INSTANCE); - } - - /** - * Gets the property delegate at the context. - * - *

If no property delegate is found, returns an empty property delegate with no properties. - * - *

Searches for block entities implementing {@link PropertyDelegateHolder}. - * - * @param ctx the context - * @return the found property delegate - */ - public static PropertyDelegate getBlockPropertyDelegate(ScreenHandlerContext ctx) { - return ctx.run((world, pos) -> { - BlockEntity be = world.getBlockEntity(pos); - if (be!=null && be instanceof PropertyDelegateHolder) { - return ((PropertyDelegateHolder)be).getPropertyDelegate(); - } - - return new ArrayPropertyDelegate(0); - }).orElse(new ArrayPropertyDelegate(0)); - } - - //extends ScreenHandler { - @Override - public boolean canUse(PlayerEntity entity) { - return (blockInventory!=null) ? blockInventory.canPlayerUse(entity) : true; - } - //} - - @Override - public boolean isFocused(WWidget widget) { - return focus == widget; - } - - @Override - public WWidget getFocus() { - return focus; - } - - @Override - public void requestFocus(WWidget widget) { - //TODO: Are there circumstances where focus can't be stolen? - if (focus==widget) return; //Nothing happens if we're already focused - if (!widget.canFocus()) return; //This is kind of a gotcha but needs to happen - if (focus!=null) focus.onFocusLost(); - focus = widget; - focus.onFocusGained(); - } - - @Override - public void releaseFocus(WWidget widget) { - if (focus==widget) { - focus = null; - widget.onFocusLost(); - } - } -} 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 815b179..0c31912 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java @@ -16,7 +16,7 @@ import net.minecraft.screen.PropertyDelegate; * They also manage the focused widget. * * @see io.github.cottonmc.cotton.gui.client.LightweightGuiDescription - * @see CottonInventoryController + * @see SyncedGuiDescription */ public interface GuiDescription { public WPanel getRootPanel(); diff --git a/src/main/java/io/github/cottonmc/cotton/gui/PropertyDelegateHolder.java b/src/main/java/io/github/cottonmc/cotton/gui/PropertyDelegateHolder.java index af61892..6aa46bd 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/PropertyDelegateHolder.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/PropertyDelegateHolder.java @@ -6,7 +6,7 @@ import net.minecraft.screen.PropertyDelegate; * This interface can be implemented on block entity classes * for providing a property delegate. * - * @see CottonInventoryController#getBlockPropertyDelegate(net.minecraft.screen.ScreenHandlerContext) + * @see SyncedGuiDescription#getBlockPropertyDelegate(net.minecraft.screen.ScreenHandlerContext) */ public interface PropertyDelegateHolder { /** diff --git a/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java b/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java new file mode 100644 index 0000000..5f2bef0 --- /dev/null +++ b/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java @@ -0,0 +1,458 @@ +package io.github.cottonmc.cotton.gui; + +import java.util.ArrayList; + +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 net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.InventoryProvider; +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.item.ItemStack; +import net.minecraft.screen.*; +import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.world.World; + +/** + * A screen handler-based GUI description for GUIs with slots. + */ +public class SyncedGuiDescription extends ScreenHandler implements GuiDescription { + + protected Inventory blockInventory; + protected PlayerInventory playerInventory; + protected World world; + protected PropertyDelegate propertyDelegate; + + protected WPanel rootPanel = new WGridPanel(); + protected int titleColor = WLabel.DEFAULT_TEXT_COLOR; + protected int darkTitleColor = WLabel.DEFAULT_DARKMODE_TEXT_COLOR; + + protected WWidget focus; + + public SyncedGuiDescription(int syncId, PlayerInventory playerInventory) { + super(null, 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); + this.blockInventory = blockInventory; + this.playerInventory = playerInventory; + this.world = playerInventory.player.world; + this.propertyDelegate = propertyDelegate; + if (propertyDelegate!=null && propertyDelegate.size()>0) this.addProperties(propertyDelegate); + } + + public WPanel getRootPanel() { + return rootPanel; + } + + public int getTitleColor() { + return LibGuiClient.config.darkMode ? darkTitleColor : titleColor; + } + + public SyncedGuiDescription setRootPanel(WPanel panel) { + this.rootPanel = panel; + return this; + } + + public SyncedGuiDescription setTitleColor(int color) { + this.titleColor = color; + return this; + } + + @Environment(EnvType.CLIENT) + public void addPainters() { + if (this.rootPanel!=null) { + this.rootPanel.setBackgroundPainter(BackgroundPainter.VANILLA); + } + } + + public void addSlotPeer(ValidatedSlot slot) { + this.addSlot(slot); + } + + @Override + public ItemStack onSlotClick(int slotNumber, int button, SlotActionType action, PlayerEntity player) { + if (action==SlotActionType.QUICK_MOVE) { + + if (slotNumber < 0) { + return ItemStack.EMPTY; + } + + if (slotNumber>=this.slots.size()) return ItemStack.EMPTY; + Slot slot = this.slots.get(slotNumber); + if (slot == null || !slot.canTakeItems(player)) { + return ItemStack.EMPTY; + } + + ItemStack remaining = ItemStack.EMPTY; + if (slot != null && slot.hasStack()) { + ItemStack toTransfer = slot.getStack(); + remaining = toTransfer.copy(); + //if (slot.inventory==blockInventory) { + if (blockInventory!=null) { + if (slot.inventory==blockInventory) { + //Try to transfer the item from the block into the player's inventory + if (!this.insertItem(toTransfer, this.playerInventory, true, player)) { + return ItemStack.EMPTY; + } + } else if (!this.insertItem(toTransfer, this.blockInventory, false, player)) { //Try to transfer the item from the player to the block + return ItemStack.EMPTY; + } + } else { + //There's no block, just swap between the player's storage and their hotbar + if (!swapHotbar(toTransfer, slotNumber, this.playerInventory, player)) { + return ItemStack.EMPTY; + } + } + + if (toTransfer.isEmpty()) { + slot.setStack(ItemStack.EMPTY); + } else { + slot.markDirty(); + } + } + + return remaining; + } else { + return super.onSlotClick(slotNumber, button, action, player); + } + } + + /** WILL MODIFY toInsert! Returns true if anything was inserted. */ + private boolean insertIntoExisting(ItemStack toInsert, Slot slot, PlayerEntity player) { + ItemStack curSlotStack = slot.getStack(); + if (!curSlotStack.isEmpty() && canStacksCombine(toInsert, curSlotStack) && slot.canTakeItems(player)) { + int combinedAmount = curSlotStack.getCount() + toInsert.getCount(); + if (combinedAmount <= toInsert.getMaxCount()) { + toInsert.setCount(0); + curSlotStack.setCount(combinedAmount); + slot.markDirty(); + return true; + } else if (curSlotStack.getCount() < toInsert.getMaxCount()) { + toInsert.decrement(toInsert.getMaxCount() - curSlotStack.getCount()); + curSlotStack.setCount(toInsert.getMaxCount()); + slot.markDirty(); + return true; + } + } + return false; + } + + /** WILL MODIFY toInsert! Returns true if anything was inserted. */ + private boolean insertIntoEmpty(ItemStack toInsert, Slot slot) { + ItemStack curSlotStack = slot.getStack(); + if (curSlotStack.isEmpty() && slot.canInsert(toInsert)) { + if (toInsert.getCount() > slot.getMaxStackAmount()) { + slot.setStack(toInsert.split(slot.getMaxStackAmount())); + } else { + slot.setStack(toInsert.split(toInsert.getCount())); + } + + slot.markDirty(); + return true; + } + + return false; + } + + private boolean insertItem(ItemStack toInsert, Inventory inventory, boolean walkBackwards, PlayerEntity player) { + //Make a unified list of slots *only from this inventory* + ArrayList inventorySlots = new ArrayList<>(); + for(Slot slot : slots) { + if (slot.inventory==inventory) inventorySlots.add(slot); + } + if (inventorySlots.isEmpty()) return false; + + //Try to insert it on top of existing stacks + boolean inserted = false; + if (walkBackwards) { + for(int i=inventorySlots.size()-1; i>=0; i--) { + Slot curSlot = inventorySlots.get(i); + if (insertIntoExisting(toInsert, curSlot, player)) inserted = true; + if (toInsert.isEmpty()) break; + } + } else { + for(int i=0; i=0; i--) { + Slot curSlot = inventorySlots.get(i); + if (insertIntoEmpty(toInsert, curSlot)) inserted = true; + if (toInsert.isEmpty()) break; + } + } else { + for(int i=0; i storageSlots = new ArrayList<>(); + ArrayList hotbarSlots = new ArrayList<>(); + boolean swapToStorage = true; + boolean inserted = false; + + for(Slot slot : slots) { + if (slot.inventory==inventory && slot instanceof ValidatedSlot) { + int index = ((ValidatedSlot)slot).getInventoryIndex(); + if (PlayerInventory.isValidHotbarIndex(index)) { + hotbarSlots.add(slot); + } else { + storageSlots.add(slot); + if (index==slotNumber) swapToStorage = false; + } + } + } + if (storageSlots.isEmpty() || hotbarSlots.isEmpty()) return false; + + if (swapToStorage) { + //swap from hotbar to storage + for(int i=0; i=wx && x=wy && yIf no inventory is found, returns {@link EmptyInventory#INSTANCE}. + * + *

Searches for these implementations in the following order: + *

    + *
  1. Blocks implementing {@code InventoryProvider}
  2. + *
  3. Block entities implementing {@code InventoryProvider}
  4. + *
  5. Block entities implementing {@code Inventory}
  6. + *
+ * + * @param ctx the context + * @return the found inventory + */ + public static Inventory getBlockInventory(ScreenHandlerContext ctx) { + 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) { + Inventory inventory = ((InventoryProvider)be).getInventory(state, world, pos); + if (inventory != null) { + return inventory; + } + } else if (be instanceof Inventory) { + return (Inventory)be; + } + } + + return EmptyInventory.INSTANCE; + }).orElse(EmptyInventory.INSTANCE); + } + + /** + * Gets the property delegate at the context. + * + *

If no property delegate is found, returns an empty property delegate with no properties. + * + *

Searches for block entities implementing {@link PropertyDelegateHolder}. + * + * @param ctx the context + * @return the found property delegate + */ + public static PropertyDelegate getBlockPropertyDelegate(ScreenHandlerContext ctx) { + return ctx.run((world, pos) -> { + BlockEntity be = world.getBlockEntity(pos); + if (be!=null && be instanceof PropertyDelegateHolder) { + return ((PropertyDelegateHolder)be).getPropertyDelegate(); + } + + return new ArrayPropertyDelegate(0); + }).orElse(new ArrayPropertyDelegate(0)); + } + + //extends ScreenHandler { + @Override + public boolean canUse(PlayerEntity entity) { + return (blockInventory!=null) ? blockInventory.canPlayerUse(entity) : true; + } + //} + + @Override + public boolean isFocused(WWidget widget) { + return focus == widget; + } + + @Override + public WWidget getFocus() { + return focus; + } + + @Override + public void requestFocus(WWidget widget) { + //TODO: Are there circumstances where focus can't be stolen? + if (focus==widget) return; //Nothing happens if we're already focused + if (!widget.canFocus()) return; //This is kind of a gotcha but needs to happen + if (focus!=null) focus.onFocusLost(); + focus = widget; + focus.onFocusGained(); + } + + @Override + public void releaseFocus(WWidget widget) { + if (focus==widget) { + focus = null; + widget.onFocusLost(); + } + } +} diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java index 5744aba..10ff4f6 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java @@ -1,5 +1,6 @@ package io.github.cottonmc.cotton.gui.client; +import io.github.cottonmc.cotton.gui.SyncedGuiDescription; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.render.DiffuseLighting; @@ -10,17 +11,16 @@ import net.minecraft.text.Style; import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; -import io.github.cottonmc.cotton.gui.CottonInventoryController; import io.github.cottonmc.cotton.gui.widget.WPanel; import io.github.cottonmc.cotton.gui.widget.WWidget; /** - * A screen for a {@link CottonInventoryController}. + * A screen for a {@link SyncedGuiDescription}. * - * @param the controller type + * @param the description type */ -public class CottonInventoryScreen extends HandledScreen implements TextHoverRendererScreen { - protected CottonInventoryController description; +public class CottonInventoryScreen extends HandledScreen implements TextHoverRendererScreen { + protected SyncedGuiDescription description; protected WWidget lastResponder = null; /** -- cgit