diff --git a/src/main/java/techreborn/client/GuiHandler.java b/src/main/java/techreborn/client/GuiHandler.java index 8e54a659a..4dccd47f0 100644 --- a/src/main/java/techreborn/client/GuiHandler.java +++ b/src/main/java/techreborn/client/GuiHandler.java @@ -1,12 +1,14 @@ package techreborn.client; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.common.network.IGuiHandler; import reborncore.api.tile.IContainerLayout; import reborncore.common.container.RebornContainer; import techreborn.client.container.*; +import techreborn.client.container.builder.ContainerBuilder; import techreborn.client.gui.*; import techreborn.manual.GuiManual; import techreborn.tiles.*; @@ -75,11 +77,11 @@ public class GuiHandler implements IGuiHandler { return new ContainerGasTurbine((TileGasTurbine) world.getTileEntity(new BlockPos(x, y, z)), player); } else if (ID == quantumTankID) { return new ContainerQuantumTank((TileQuantumTank) world.getTileEntity(new BlockPos(x, y, z)), player); - } else if (ID == digitalChestID) { - return new ContainerDigitalChest((TileDigitalChest) world.getTileEntity(new BlockPos(x, y, z)), player); - } else if (ID == quantumChestID) { - return new ContainerQuantumChest((TileQuantumChest) world.getTileEntity(new BlockPos(x, y, z)), player); - } else if (ID == centrifugeID) { + } else if (ID == GuiHandler.digitalChestID || ID == GuiHandler.quantumChestID) { + return new ContainerBuilder().player(player.inventory).inventory().hotbar().addInventory() + .tile((IInventory) world.getTileEntity(new BlockPos(x, y, z))).slot(0, 80, 17).output(1, 80, 53) + .fake(2, 59, 42).addInventory().create(); + } else if (ID == GuiHandler.centrifugeID) { container = new ContainerCentrifuge(player, (TileCentrifuge) world.getTileEntity(new BlockPos(x, y, z))); } else if (ID == rollingMachineID) { return new ContainerRollingMachine((TileRollingMachine) world.getTileEntity(new BlockPos(x, y, z)), player); diff --git a/src/main/java/techreborn/client/container/ContainerDigitalChest.java b/src/main/java/techreborn/client/container/ContainerDigitalChest.java deleted file mode 100644 index 37f70db62..000000000 --- a/src/main/java/techreborn/client/container/ContainerDigitalChest.java +++ /dev/null @@ -1,41 +0,0 @@ -package techreborn.client.container; - -import net.minecraft.entity.player.EntityPlayer; -import reborncore.client.gui.slots.BaseSlot; -import reborncore.client.gui.slots.SlotFake; -import reborncore.client.gui.slots.SlotOutput; -import reborncore.common.container.RebornContainer; -import techreborn.tiles.TileDigitalChest; - -public class ContainerDigitalChest extends RebornContainer { - public TileDigitalChest tileDigitalChest; - public EntityPlayer player; - - public ContainerDigitalChest(TileDigitalChest tileDigitalChest, EntityPlayer player) { - super(); - this.tileDigitalChest = tileDigitalChest; - this.player = player; - - this.addSlotToContainer(new BaseSlot(tileDigitalChest.inventory, 0, 80, 17)); - this.addSlotToContainer(new SlotOutput(tileDigitalChest.inventory, 1, 80, 53)); - this.addSlotToContainer(new SlotFake(tileDigitalChest.inventory, 2, 59, 42, false, false, Integer.MAX_VALUE)); - - int i; - - for (i = 0; i < 3; ++i) { - for (int j = 0; j < 9; ++j) { - this.addSlotToContainer(new BaseSlot(player.inventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18)); - } - } - - for (i = 0; i < 9; ++i) { - this.addSlotToContainer(new BaseSlot(player.inventory, i, 8 + i * 18, 142)); - } - } - - @Override - public boolean canInteractWith(EntityPlayer player) { - return true; - } - -} \ No newline at end of file diff --git a/src/main/java/techreborn/client/container/ContainerQuantumChest.java b/src/main/java/techreborn/client/container/ContainerQuantumChest.java deleted file mode 100644 index c1e6641b5..000000000 --- a/src/main/java/techreborn/client/container/ContainerQuantumChest.java +++ /dev/null @@ -1,41 +0,0 @@ -package techreborn.client.container; - -import net.minecraft.entity.player.EntityPlayer; -import reborncore.client.gui.slots.BaseSlot; -import reborncore.client.gui.slots.SlotFake; -import reborncore.client.gui.slots.SlotOutput; -import reborncore.common.container.RebornContainer; -import techreborn.tiles.TileQuantumChest; - -public class ContainerQuantumChest extends RebornContainer { - public TileQuantumChest tileQuantumChest; - public EntityPlayer player; - - public ContainerQuantumChest(TileQuantumChest tileQuantumChest, EntityPlayer player) { - super(); - this.tileQuantumChest = tileQuantumChest; - this.player = player; - - this.addSlotToContainer(new BaseSlot(tileQuantumChest.inventory, 0, 80, 17)); - this.addSlotToContainer(new SlotOutput(tileQuantumChest.inventory, 1, 80, 53)); - this.addSlotToContainer(new SlotFake(tileQuantumChest.inventory, 2, 59, 42, false, false, Integer.MAX_VALUE)); - - int i; - - for (i = 0; i < 3; ++i) { - for (int j = 0; j < 9; ++j) { - this.addSlotToContainer(new BaseSlot(player.inventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18)); - } - } - - for (i = 0; i < 9; ++i) { - this.addSlotToContainer(new BaseSlot(player.inventory, i, 8 + i * 18, 142)); - } - } - - @Override - public boolean canInteractWith(EntityPlayer player) { - return true; - } - -} diff --git a/src/main/java/techreborn/client/container/builder/ArmorSlot.java b/src/main/java/techreborn/client/container/builder/ArmorSlot.java new file mode 100644 index 000000000..266a64362 --- /dev/null +++ b/src/main/java/techreborn/client/container/builder/ArmorSlot.java @@ -0,0 +1,26 @@ +package techreborn.client.container.builder; + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.util.ResourceLocation; + +import techreborn.lib.ModInfo; + +public class ArmorSlot extends FilteredSlot { + + public ArmorSlot(final EntityEquipmentSlot armorType, final InventoryPlayer inventory, final int index, + final int xPosition, final int yPosition) { + + super(inventory, index, xPosition, yPosition); + + this.setFilter(stack -> stack != null && stack.getItem().isValidArmor(stack, armorType, inventory.player)); + + this.setBackgroundLocation( + new ResourceLocation(ModInfo.MOD_ID, "textures/gui/armor_" + armorType.getName() + ".png")); + } + + @Override + public int getSlotStackLimit() { + return 1; + } +} diff --git a/src/main/java/techreborn/client/container/builder/BuiltContainer.java b/src/main/java/techreborn/client/container/builder/BuiltContainer.java new file mode 100644 index 000000000..7ecd5636b --- /dev/null +++ b/src/main/java/techreborn/client/container/builder/BuiltContainer.java @@ -0,0 +1,134 @@ +package techreborn.client.container.builder; + +import org.apache.commons.lang3.Range; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +import reborncore.common.util.ItemUtils; + +import java.util.List; +import java.util.function.Predicate; + +final class BuiltContainer extends Container { + + private final Predicate canInteract; + private final List> playerSlotRanges; + private final List> tileSlotRanges; + + public BuiltContainer(final Predicate canInteract, final List> playerSlotRange, + final List> tileSlotRange) { + this.canInteract = canInteract; + + this.playerSlotRanges = playerSlotRange; + this.tileSlotRanges = tileSlotRange; + } + + public void addSlot(final Slot slot) { + this.addSlotToContainer(slot); + } + + @Override + public boolean canInteractWith(final EntityPlayer playerIn) { + return this.canInteract.test(playerIn); + } + + @Override + public ItemStack transferStackInSlot(final EntityPlayer player, final int index) { + + ItemStack originalStack = ItemStack.EMPTY; + + final Slot slot = this.inventorySlots.get(index); + + if (slot != null && slot.getHasStack()) { + + final ItemStack stackInSlot = slot.getStack(); + originalStack = stackInSlot.copy(); + + boolean shifted = false; + + for (final Range range : this.playerSlotRanges) + if (range.contains(index)) { + + this.shiftToTile(stackInSlot); + shifted = true; + break; + } + + if (!shifted) + for (final Range range : this.tileSlotRanges) + if (range.contains(index)) { + this.shiftToPlayer(stackInSlot); + shifted = true; + break; + } + + slot.onSlotChange(stackInSlot, originalStack); + if (stackInSlot.getCount() <= 0) + slot.putStack(ItemStack.EMPTY); + else + slot.onSlotChanged(); + if (stackInSlot.getCount() == originalStack.getCount()) + return ItemStack.EMPTY; + slot.onTake(player, stackInSlot); + } + return originalStack; + } + + protected boolean shiftItemStack(final ItemStack stackToShift, final int start, final int end) { + boolean changed = false; + if (stackToShift.isStackable()) { + for (int slotIndex = start; stackToShift.getCount() > 0 && slotIndex < end; slotIndex++) { + final Slot slot = this.inventorySlots.get(slotIndex); + final ItemStack stackInSlot = slot.getStack(); + if (stackInSlot != ItemStack.EMPTY && ItemUtils.isItemEqual(stackInSlot, stackToShift, true, true)) { + final int resultingStackSize = stackInSlot.getCount() + stackToShift.getCount(); + final int max = Math.min(stackToShift.getMaxStackSize(), slot.getSlotStackLimit()); + if (resultingStackSize <= max) { + stackToShift.setCount(0); + stackInSlot.setCount(resultingStackSize); + slot.onSlotChanged(); + changed = true; + } else if (stackInSlot.getCount() < max) { + stackToShift.setCount(-(max - stackInSlot.getCount())); + stackInSlot.setCount(max); + slot.onSlotChanged(); + changed = true; + } + } + } + } + if (stackToShift.getCount() > 0) { + for (int slotIndex = start; stackToShift.getCount() > 0 && slotIndex < end; slotIndex++) { + final Slot slot = this.inventorySlots.get(slotIndex); + ItemStack stackInSlot = slot.getStack(); + if (stackInSlot == ItemStack.EMPTY) { + final int max = Math.min(stackToShift.getMaxStackSize(), slot.getSlotStackLimit()); + stackInSlot = stackToShift.copy(); + stackInSlot.setCount(Math.min(stackToShift.getCount(), max)); + stackToShift.setCount(-stackInSlot.getCount()); + slot.putStack(stackInSlot); + slot.onSlotChanged(); + changed = true; + } + } + } + return changed; + } + + private boolean shiftToTile(final ItemStack stackToShift) { + for (final Range range : this.tileSlotRanges) + if (this.shiftItemStack(stackToShift, range.getMinimum(), range.getMaximum())) + return true; + return false; + } + + private boolean shiftToPlayer(final ItemStack stackToShift) { + for (final Range range : this.playerSlotRanges) + if (this.shiftItemStack(stackToShift, range.getMinimum(), range.getMaximum())) + return true; + return false; + } +} \ No newline at end of file diff --git a/src/main/java/techreborn/client/container/builder/ContainerBuilder.java b/src/main/java/techreborn/client/container/builder/ContainerBuilder.java new file mode 100644 index 000000000..7043ba521 --- /dev/null +++ b/src/main/java/techreborn/client/container/builder/ContainerBuilder.java @@ -0,0 +1,56 @@ +package techreborn.client.container.builder; + +import org.apache.commons.lang3.Range; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +public class ContainerBuilder { + private Predicate canInteract = player -> true; + + final List slots; + final List> playerInventoryRanges, tileInventoryRanges; + + public ContainerBuilder() { + this.slots = new ArrayList<>(); + this.playerInventoryRanges = new ArrayList<>(); + this.tileInventoryRanges = new ArrayList<>(); + } + + public ContainerBuilder interact(final Predicate canInteract) { + this.canInteract = canInteract; + return this; + } + + public ContainerPlayerInventoryBuilder player(final InventoryPlayer player) { + return new ContainerPlayerInventoryBuilder(this, player); + } + + public ContainerTileInventoryBuilder tile(final IInventory tile) { + return new ContainerTileInventoryBuilder(this, tile); + } + + void addPlayerInventoryRange(final Range range) { + this.playerInventoryRanges.add(range); + } + + void addTileInventoryRange(final Range range) { + this.tileInventoryRanges.add(range); + } + + public BuiltContainer create() { + final BuiltContainer built = new BuiltContainer(this.canInteract, this.playerInventoryRanges, + this.tileInventoryRanges); + + this.slots.forEach(built::addSlot); + + this.slots.clear(); + return built; + } +} diff --git a/src/main/java/techreborn/client/container/builder/ContainerPlayerInventoryBuilder.java b/src/main/java/techreborn/client/container/builder/ContainerPlayerInventoryBuilder.java new file mode 100644 index 000000000..89a1242e1 --- /dev/null +++ b/src/main/java/techreborn/client/container/builder/ContainerPlayerInventoryBuilder.java @@ -0,0 +1,127 @@ +package techreborn.client.container.builder; + +import org.apache.commons.lang3.Range; + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; + +import reborncore.client.gui.slots.BaseSlot; + +public final class ContainerPlayerInventoryBuilder { + + private final InventoryPlayer player; + private final ContainerBuilder parent; + private Range main; + private Range hotbar; + private Range armor; + + ContainerPlayerInventoryBuilder(final ContainerBuilder parent, final InventoryPlayer player) { + this.player = player; + this.parent = parent; + } + + public ContainerPlayerInventoryBuilder inventory(final int xStart, final int yStart) { + final int startIndex = this.parent.slots.size(); + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 9; ++j) + this.parent.slots.add(new BaseSlot(this.player, j + i * 9 + 9, xStart + j * 18, yStart + i * 18)); + this.main = Range.between(startIndex, this.parent.slots.size() - 1); + return this; + } + + public ContainerPlayerInventoryBuilder hotbar(final int xStart, final int yStart) { + final int startIndex = this.parent.slots.size(); + for (int i = 0; i < 9; ++i) + this.parent.slots.add(new BaseSlot(this.player, i, xStart + i * 18, yStart)); + this.hotbar = Range.between(startIndex, this.parent.slots.size() - 1); + return this; + } + + public ContainerPlayerInventoryBuilder inventory() { + return this.inventory(8, 84); + } + + public ContainerPlayerInventoryBuilder hotbar() { + return this.hotbar(8, 142); + } + + private ContainerPlayerInventoryBuilder armor(final int index, final int xStart, final int yStart, + final EntityEquipmentSlot slotType) { + this.parent.slots.add(new ArmorSlot(slotType, this.player, index, xStart, yStart)); + return this; + } + + public ContainerPlayerInventoryBuilder helmet(final int xStart, final int yStart) { + return this.armor(this.player.getSizeInventory() - 2, xStart, yStart, EntityEquipmentSlot.HEAD); + } + + public ContainerPlayerInventoryBuilder chestplate(final int xStart, final int yStart) { + return this.armor(this.player.getSizeInventory() - 3, xStart, yStart, EntityEquipmentSlot.CHEST); + } + + public ContainerPlayerInventoryBuilder leggings(final int xStart, final int yStart) { + return this.armor(this.player.getSizeInventory() - 4, xStart, yStart, EntityEquipmentSlot.LEGS); + } + + public ContainerPlayerInventoryBuilder boots(final int xStart, final int yStart) { + return this.armor(this.player.getSizeInventory() - 5, xStart, yStart, EntityEquipmentSlot.FEET); + } + + public ContainerPlayerInventoryBuilder armor(final int xStart, final int yStart) { + return this.helmet(xStart, yStart).chestplate(xStart, yStart + 19).leggings(xStart, yStart + 38).boots(xStart, + yStart + 57); + } + + public ContainerBuilder addInventory() { + if (this.hotbar != null) + this.parent.addPlayerInventoryRange(this.hotbar); + if (this.main != null) + this.parent.addPlayerInventoryRange(this.main); + if (this.armor != null) + this.parent.addTileInventoryRange(this.armor); + + return this.parent; + } + + public static final class ContainerPlayerArmorInventoryBuilder { + private final ContainerPlayerInventoryBuilder parent; + private final int startIndex; + + public ContainerPlayerArmorInventoryBuilder(final ContainerPlayerInventoryBuilder parent) { + this.parent = parent; + this.startIndex = parent.parent.slots.size(); + } + + private ContainerPlayerArmorInventoryBuilder armor(final int index, final int xStart, final int yStart, + final EntityEquipmentSlot slotType) { + this.parent.parent.slots.add(new ArmorSlot(slotType, this.parent.player, index, xStart, yStart)); + return this; + } + + public ContainerPlayerArmorInventoryBuilder helmet(final int xStart, final int yStart) { + return this.armor(this.parent.player.getSizeInventory() - 2, xStart, yStart, EntityEquipmentSlot.HEAD); + } + + public ContainerPlayerArmorInventoryBuilder chestplate(final int xStart, final int yStart) { + return this.armor(this.parent.player.getSizeInventory() - 3, xStart, yStart, EntityEquipmentSlot.CHEST); + } + + public ContainerPlayerArmorInventoryBuilder leggings(final int xStart, final int yStart) { + return this.armor(this.parent.player.getSizeInventory() - 4, xStart, yStart, EntityEquipmentSlot.LEGS); + } + + public ContainerPlayerArmorInventoryBuilder boots(final int xStart, final int yStart) { + return this.armor(this.parent.player.getSizeInventory() - 5, xStart, yStart, EntityEquipmentSlot.FEET); + } + + public ContainerPlayerArmorInventoryBuilder complete(final int xStart, final int yStart) { + return this.helmet(xStart, yStart).chestplate(xStart, yStart + 19).leggings(xStart, yStart + 38) + .boots(xStart, yStart + 57); + } + + public ContainerPlayerInventoryBuilder addArmor() { + this.parent.armor = Range.between(this.startIndex, this.parent.parent.slots.size() - 1); + return this.parent; + } + } +} \ No newline at end of file diff --git a/src/main/java/techreborn/client/container/builder/ContainerTileInventoryBuilder.java b/src/main/java/techreborn/client/container/builder/ContainerTileInventoryBuilder.java new file mode 100644 index 000000000..881300116 --- /dev/null +++ b/src/main/java/techreborn/client/container/builder/ContainerTileInventoryBuilder.java @@ -0,0 +1,42 @@ +package techreborn.client.container.builder; + +import org.apache.commons.lang3.Range; + +import net.minecraft.inventory.IInventory; + +import reborncore.client.gui.slots.BaseSlot; +import reborncore.client.gui.slots.SlotFake; +import reborncore.client.gui.slots.SlotOutput; + +public class ContainerTileInventoryBuilder { + + private final IInventory tile; + private final ContainerBuilder parent; + private final int rangeStart; + + ContainerTileInventoryBuilder(final ContainerBuilder parent, final IInventory tile) { + this.tile = tile; + this.parent = parent; + this.rangeStart = parent.slots.size(); + } + + public ContainerTileInventoryBuilder slot(final int index, final int x, final int y) { + this.parent.slots.add(new BaseSlot(this.tile, index, x, y)); + return this; + } + + public ContainerTileInventoryBuilder output(final int index, final int x, final int y) { + this.parent.slots.add(new SlotOutput(this.tile, index, x, y)); + return this; + } + + public ContainerTileInventoryBuilder fake(final int index, final int x, final int y) { + this.parent.slots.add(new SlotFake(this.tile, index, x, y, false, false, Integer.MAX_VALUE)); + return this; + } + + public ContainerBuilder addInventory() { + this.parent.tileInventoryRanges.add(Range.between(this.rangeStart, this.parent.slots.size() - 1)); + return this.parent; + } +} diff --git a/src/main/java/techreborn/client/container/builder/FilteredSlot.java b/src/main/java/techreborn/client/container/builder/FilteredSlot.java new file mode 100644 index 000000000..9c77aecaa --- /dev/null +++ b/src/main/java/techreborn/client/container/builder/FilteredSlot.java @@ -0,0 +1,26 @@ +package techreborn.client.container.builder; + +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +import java.util.function.Predicate; + +public class FilteredSlot extends Slot { + + private Predicate filter; + + public FilteredSlot(final IInventory inventory, final int index, final int xPosition, final int yPosition) { + super(inventory, index, xPosition, yPosition); + } + + public FilteredSlot setFilter(final Predicate filter) { + this.filter = filter; + return this; + } + + @Override + public boolean isItemValid(final ItemStack stack) { + return this.filter.test(stack); + } +} diff --git a/src/main/java/techreborn/client/gui/GuiDigitalChest.java b/src/main/java/techreborn/client/gui/GuiDigitalChest.java index 6b7f95fa4..4e683359c 100644 --- a/src/main/java/techreborn/client/gui/GuiDigitalChest.java +++ b/src/main/java/techreborn/client/gui/GuiDigitalChest.java @@ -6,7 +6,8 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.translation.I18n; -import techreborn.client.container.ContainerDigitalChest; + +import techreborn.client.container.builder.ContainerBuilder; import techreborn.tiles.TileDigitalChest; public class GuiDigitalChest extends GuiContainer { @@ -16,8 +17,9 @@ public class GuiDigitalChest extends GuiContainer { TileDigitalChest tile; - public GuiDigitalChest(EntityPlayer player, TileDigitalChest tile) { - super(new ContainerDigitalChest(tile, player)); + public GuiDigitalChest(final EntityPlayer player, final TileDigitalChest tile) { + super(new ContainerBuilder().player(player.inventory).inventory().hotbar().addInventory().tile(tile).slot(0, 80, 17) + .output(1, 80, 53).fake(2, 59, 42).addInventory().create()); this.xSize = 176; this.ySize = 167; this.tile = tile; diff --git a/src/main/java/techreborn/client/gui/GuiQuantumChest.java b/src/main/java/techreborn/client/gui/GuiQuantumChest.java index f8d31d0e0..36215a0c8 100644 --- a/src/main/java/techreborn/client/gui/GuiQuantumChest.java +++ b/src/main/java/techreborn/client/gui/GuiQuantumChest.java @@ -7,7 +7,8 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.translation.I18n; import reborncore.common.util.ItemUtils; -import techreborn.client.container.ContainerQuantumChest; + +import techreborn.client.container.builder.ContainerBuilder; import techreborn.tiles.TileQuantumChest; public class GuiQuantumChest extends GuiContainer { @@ -17,8 +18,9 @@ public class GuiQuantumChest extends GuiContainer { TileQuantumChest tile; - public GuiQuantumChest(EntityPlayer player, TileQuantumChest tile) { - super(new ContainerQuantumChest(tile, player)); + public GuiQuantumChest(final EntityPlayer player, final TileQuantumChest tile) { + super(new ContainerBuilder().player(player.inventory).inventory().hotbar().addInventory().tile(tile) + .slot(0, 80, 17).output(1, 80, 53).fake(2, 59, 42).addInventory().create()); this.xSize = 176; this.ySize = 167; this.tile = tile;