diff --git a/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java b/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java index 6eda022..09a2fed 100644 --- a/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java +++ b/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java @@ -76,7 +76,7 @@ public class ItemFilter extends ItemStackHandler { } else if (id == 1 && this.canPopulateFromInventories) { // populate filter from inventories for (Direction direction : Direction.values()) { - IItemHandler handler = this.pipe.getItemHandler(direction, false); + IItemHandler handler = this.pipe.getItemHandler(direction, null); if (handler == null) continue; for (int i = 0; i < handler.getSlots(); i++) { diff --git a/src/main/java/de/ellpeck/prettypipes/network/NetworkLock.java b/src/main/java/de/ellpeck/prettypipes/network/NetworkLock.java new file mode 100644 index 0000000..80697c1 --- /dev/null +++ b/src/main/java/de/ellpeck/prettypipes/network/NetworkLock.java @@ -0,0 +1,14 @@ +package de.ellpeck.prettypipes.network; + +public class NetworkLock { + + public final NetworkLocation location; + public final int slot; + public final int amount; + + public NetworkLock(NetworkLocation location, int slot, int amount) { + this.location = location; + this.slot = slot; + this.amount = amount; + } +} diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeItem.java b/src/main/java/de/ellpeck/prettypipes/network/PipeItem.java index 4a51ad7..34aaced 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeItem.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeItem.java @@ -1,6 +1,7 @@ package de.ellpeck.prettypipes.network; import de.ellpeck.prettypipes.Utility; +import de.ellpeck.prettypipes.pipe.IPipeConnectable; import de.ellpeck.prettypipes.pipe.PipeTileEntity; import net.minecraft.block.BlockState; import net.minecraft.block.ILiquidContainer; @@ -172,10 +173,13 @@ public class PipeItem implements INBTSerializable, ILiquidContainer private ItemStack store(PipeTileEntity currPipe) { Direction dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe()); - IItemHandler handler = currPipe.getItemHandler(dir, true); - if (handler == null) - return this.stack; - return ItemHandlerHelper.insertItemStacked(handler, this.stack, false); + IPipeConnectable connectable = currPipe.getPipeConnectable(dir); + if (connectable != null) + return connectable.insertItem(currPipe.getWorld(), currPipe.getPos(), dir, this); + IItemHandler handler = currPipe.getItemHandler(dir, this); + if (handler != null) + return ItemHandlerHelper.insertItemStacked(handler, this.stack, false); + return this.stack; } private PipeTileEntity getNextTile(PipeTileEntity currPipe, boolean progress) { diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java index d2d1a8e..ae2a54a 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java @@ -50,6 +50,7 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL private final Map> nodeToConnectedNodes = new HashMap<>(); private final Map tileCache = new HashMap<>(); private final ListMultimap pipeItems = ArrayListMultimap.create(); + private final ListMultimap networkLocks = ArrayListMultimap.create(); private final World world; public PipeNetwork(World world) { @@ -189,7 +190,7 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL if (!pipe.canNetworkSee()) continue; for (Direction dir : Direction.values()) { - IItemHandler handler = pipe.getItemHandler(dir, false); + IItemHandler handler = pipe.getItemHandler(dir, null); if (handler == null) continue; // check if this handler already exists (double-connected pipes, double chests etc.) @@ -210,6 +211,24 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL return info; } + public void createNetworkLock(NetworkLock lock) { + this.networkLocks.put(lock.location.pos, lock); + } + + public void resolveNetworkLock(NetworkLock lock) { + this.networkLocks.remove(lock.location.pos, lock); + } + + public List getNetworkLocks(BlockPos pos) { + return this.networkLocks.get(pos); + } + + public int getLockedAmount(BlockPos pos, int slot) { + return this.getNetworkLocks(pos).stream() + .filter(l -> l.slot == slot) + .mapToInt(l -> l.amount).sum(); + } + private void refreshNode(BlockPos pos, BlockState state) { this.startProfile("refresh_node"); this.graph.removeAllEdges(new ArrayList<>(this.graph.edgesOf(pos))); diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/IPipeConnectable.java b/src/main/java/de/ellpeck/prettypipes/pipe/IPipeConnectable.java index a1752e4..c9c3e86 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/IPipeConnectable.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/IPipeConnectable.java @@ -1,6 +1,8 @@ package de.ellpeck.prettypipes.pipe; +import de.ellpeck.prettypipes.network.PipeItem; import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -8,9 +10,13 @@ import net.minecraftforge.items.IItemHandler; public interface IPipeConnectable { - ConnectionType getConnectionType(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction); + ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction); - default IItemHandler getItemHandler(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction, boolean force) { + default IItemHandler getItemHandler(World world, BlockPos pipePos, Direction direction, PipeItem item) { return null; } + + default ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) { + return item.stack; + } } diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/PipeBlock.java b/src/main/java/de/ellpeck/prettypipes/pipe/PipeBlock.java index 21d680b..1897415 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/PipeBlock.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/PipeBlock.java @@ -72,7 +72,7 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable { PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos); if (tile == null) return ActionResultType.PASS; - if (!tile.isConnectedInventory(false)) + if (!tile.isConnectedInventory()) return ActionResultType.PASS; if (!worldIn.isRemote) NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos); @@ -161,7 +161,7 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable { BlockState offState = world.getBlockState(offset); Block block = offState.getBlock(); if (block instanceof IPipeConnectable) - return ((IPipeConnectable) block).getConnectionType(world, offset, offState, pos, direction.getOpposite()); + return ((IPipeConnectable) block).getConnectionType(world, pos, direction); TileEntity tile = world.getTileEntity(offset); if (tile != null) { IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()).orElse(null); @@ -185,7 +185,7 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable { public static void onStateChanged(World world, BlockPos pos, BlockState newState) { PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, world, pos); - if (tile != null && !tile.isConnectedInventory(false)) + if (tile != null && !tile.isConnectedInventory()) Utility.dropInventory(tile, tile.modules); PipeNetwork network = PipeNetwork.get(world); @@ -252,8 +252,9 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable { } @Override - public ConnectionType getConnectionType(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction) { - if (state.get(DIRECTIONS.get(direction)) == ConnectionType.BLOCKED) + public ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction) { + BlockState state = world.getBlockState(pipePos.offset(direction)); + if (state.get(DIRECTIONS.get(direction.getOpposite())) == ConnectionType.BLOCKED) return ConnectionType.BLOCKED; return ConnectionType.CONNECTED; } diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java index 2a38546..aac165e 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java @@ -139,7 +139,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack))) return null; for (Direction dir : Direction.values()) { - IItemHandler handler = this.getItemHandler(dir, force); + IItemHandler handler = this.getItemHandler(dir, null); if (handler == null) continue; if (!ItemHandlerHelper.insertItem(handler, stack, true).isEmpty()) @@ -192,7 +192,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide return this.streamModules().allMatch(m -> m.getRight().canPipeWork(m.getLeft(), this)); } - public IItemHandler getItemHandler(Direction dir, boolean force) { + public IItemHandler getItemHandler(Direction dir, PipeItem item) { if (!this.isConnected(dir)) return null; BlockPos pos = this.pos.offset(dir); @@ -208,21 +208,25 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide if (handler != null) return handler; } - BlockState state = this.world.getBlockState(pos); - if (state.getBlock() instanceof IPipeConnectable) { - IItemHandler handler = ((IPipeConnectable) state.getBlock()).getItemHandler(this.world, pos, state, this.pos, dir, force); - if (handler != null) - return handler; - } + IPipeConnectable connectable = this.getPipeConnectable(dir); + if (connectable != null) + return connectable.getItemHandler(this.world, this.pos, dir, item); return null; } - public boolean isConnectedInventory(Direction dir, boolean force) { - return this.getItemHandler(dir, force) != null; + public IPipeConnectable getPipeConnectable(Direction dir) { + BlockState state = this.world.getBlockState(this.pos.offset(dir)); + if (state.getBlock() instanceof IPipeConnectable) + return (IPipeConnectable) state.getBlock(); + return null; } - public boolean isConnectedInventory(boolean force) { - return Arrays.stream(Direction.values()).anyMatch(dir -> this.isConnectedInventory(dir, force)); + public boolean isConnectedInventory(Direction dir) { + return this.getItemHandler(dir, null) != null; + } + + public boolean isConnectedInventory() { + return Arrays.stream(Direction.values()).anyMatch(this::isConnectedInventory); } public boolean canNetworkSee() { diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/modules/extraction/ExtractionModuleItem.java b/src/main/java/de/ellpeck/prettypipes/pipe/modules/extraction/ExtractionModuleItem.java index 49ef83c..ebf724d 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/modules/extraction/ExtractionModuleItem.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/modules/extraction/ExtractionModuleItem.java @@ -39,7 +39,7 @@ public class ExtractionModuleItem extends ModuleItem { PipeNetwork network = PipeNetwork.get(tile.getWorld()); for (Direction dir : Direction.values()) { - IItemHandler handler = tile.getItemHandler(dir, false); + IItemHandler handler = tile.getItemHandler(dir, null); if (handler == null) continue; for (int j = 0; j < handler.getSlots(); j++) { diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalBlock.java b/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalBlock.java index 76ee455..c6acce9 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalBlock.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalBlock.java @@ -1,9 +1,16 @@ package de.ellpeck.prettypipes.terminal; -import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui; -import net.minecraft.block.ContainerBlock; +import de.ellpeck.prettypipes.Utility; +import de.ellpeck.prettypipes.misc.ItemEqualityType; +import de.ellpeck.prettypipes.network.PipeItem; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; +import net.minecraft.world.World; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; import javax.annotation.Nullable; @@ -14,4 +21,29 @@ public class CraftingTerminalBlock extends ItemTerminalBlock { public TileEntity createNewTileEntity(IBlockReader worldIn) { return new CraftingTerminalTileEntity(); } + + @Override + public ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) { + BlockPos pos = pipePos.offset(direction); + CraftingTerminalTileEntity tile = Utility.getTileEntity(CraftingTerminalTileEntity.class, world, pos); + if (tile != null) { + int lowestFitting = -1; + for (int i = 0; i < tile.craftItems.getSlots(); i++) { + ItemStack stack = tile.getRequestedCraftItem(i); + if (!ItemHandlerHelper.canItemStacksStackRelaxed(stack, item.stack)) + continue; + if (lowestFitting < 0 || stack.getCount() < tile.getRequestedCraftItem(lowestFitting).getCount()) + lowestFitting = i; + } + ItemStack remain = item.stack; + if (lowestFitting >= 0) { + remain = tile.craftItems.insertItem(lowestFitting, item.stack, false); + if (remain.isEmpty()) + return ItemStack.EMPTY; + } + return ItemHandlerHelper.insertItemStacked(tile.items, remain, false); + } + return item.stack; + } + } diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalTileEntity.java b/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalTileEntity.java index 80aaedd..0eb3756 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalTileEntity.java @@ -7,17 +7,39 @@ import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.items.ItemStackHandler; import javax.annotation.Nullable; public class CraftingTerminalTileEntity extends ItemTerminalTileEntity { + public final ItemStackHandler craftItems = new ItemStackHandler(9); + public CraftingTerminalTileEntity() { super(Registry.craftingTerminalTileEntity); } + public ItemStack getRequestedCraftItem(int slot) { + // TODO put ghost slot contents here + return this.craftItems.getStackInSlot(slot); + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + compound.put("craft_items", this.craftItems.serializeNBT()); + return super.write(compound); + } + + @Override + public void read(CompoundNBT compound) { + this.craftItems.deserializeNBT(compound.getCompound("craft_items")); + super.read(compound); + } + @Override public ITextComponent getDisplayName() { return new TranslationTextComponent("container." + PrettyPipes.ID + ".crafting_terminal"); diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalBlock.java b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalBlock.java index c3f543d..dd09f82 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalBlock.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalBlock.java @@ -25,6 +25,7 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.World; import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; import javax.annotation.Nullable; import java.util.List; @@ -63,18 +64,17 @@ public class ItemTerminalBlock extends ContainerBlock implements IPipeConnectabl } @Override - public ConnectionType getConnectionType(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction) { + public ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction) { return ConnectionType.CONNECTED; } @Override - public IItemHandler getItemHandler(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction, boolean force) { - if (force) { - ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, world, pos); - if (tile != null) - return tile.items; - } - return null; + public ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) { + BlockPos pos = pipePos.offset(direction); + ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, world, pos); + if (tile != null) + return ItemHandlerHelper.insertItemStacked(tile.items, item.stack, false); + return item.stack; } @Override diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java index 3a2f112..af8f9a8 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java @@ -6,10 +6,7 @@ import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.misc.EquatableItemStack; import de.ellpeck.prettypipes.misc.ItemEqualityType; import de.ellpeck.prettypipes.misc.ItemOrder; -import de.ellpeck.prettypipes.network.NetworkItem; -import de.ellpeck.prettypipes.network.NetworkLocation; -import de.ellpeck.prettypipes.network.PipeItem; -import de.ellpeck.prettypipes.network.PipeNetwork; +import de.ellpeck.prettypipes.network.*; import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketNetworkItems; import de.ellpeck.prettypipes.pipe.PipeTileEntity; @@ -50,7 +47,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine } }; public Map networkItems; - private final Queue> pendingRequests = new ArrayDeque<>(); + private final Queue pendingRequests = new ArrayDeque<>(); protected ItemTerminalTileEntity(TileEntityType tileEntityTypeIn) { super(tileEntityTypeIn); @@ -82,13 +79,11 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine } if (!this.pendingRequests.isEmpty()) { - Triple request = this.pendingRequests.remove(); - NetworkLocation location = request.getLeft(); - int slot = request.getMiddle(); - int amount = request.getRight(); - ItemStack extracted = location.handler.extractItem(slot, amount, true); - if (network.routeItemToLocation(location.pipePos, location.pos, pipe.getPos(), this.pos, speed -> new PipeItem(extracted, speed))) { - location.handler.extractItem(slot, extracted.getCount(), false); + NetworkLock request = this.pendingRequests.remove(); + network.resolveNetworkLock(request); + ItemStack extracted = request.location.handler.extractItem(request.slot, request.amount, true); + if (network.routeItemToLocation(request.location.pipePos, request.location.pos, pipe.getPos(), this.pos, speed -> new PipeItem(extracted, speed))) { + request.location.handler.extractItem(request.slot, extracted.getCount(), false); update = true; } } @@ -132,16 +127,23 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine PipeNetwork network = PipeNetwork.get(this.world); network.startProfile("terminal_request_item"); EquatableItemStack equatable = new EquatableItemStack(stack); + this.updateItems(); NetworkItem item = this.networkItems.get(equatable); if (item != null) { int remain = stack.getCount(); locations: for (NetworkLocation location : item.getLocations()) { for (int slot : location.getStackSlots(stack, ItemEqualityType.NBT)) { - ItemStack extracted = location.handler.extractItem(slot, remain, true); - if (!extracted.isEmpty()) { - this.pendingRequests.add(Triple.of(location, slot, extracted.getCount())); - remain -= extracted.getCount(); + ItemStack inSlot = location.handler.extractItem(slot, Integer.MAX_VALUE, true); + if (inSlot.isEmpty()) + continue; + inSlot.shrink(network.getLockedAmount(location.pos, slot)); + if (inSlot.getCount() > 0) { + int extract = Math.min(inSlot.getCount(), remain); + NetworkLock lock = new NetworkLock(location, slot, extract); + this.pendingRequests.add(lock); + network.createNetworkLock(lock); + remain -= extract; if (remain <= 0) break locations; } diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/containers/CraftingTerminalContainer.java b/src/main/java/de/ellpeck/prettypipes/terminal/containers/CraftingTerminalContainer.java index dcfe991..2f883a1 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/containers/CraftingTerminalContainer.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/containers/CraftingTerminalContainer.java @@ -1,19 +1,74 @@ package de.ellpeck.prettypipes.terminal.containers; +import de.ellpeck.prettypipes.Utility; +import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity; +import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.CraftResultInventory; +import net.minecraft.inventory.CraftingInventory; +import net.minecraft.inventory.IInventory; import net.minecraft.inventory.container.ContainerType; +import net.minecraft.inventory.container.CraftingResultSlot; import net.minecraft.inventory.container.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ICraftingRecipe; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.network.play.server.SSetSlotPacket; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.items.SlotItemHandler; +import org.apache.commons.lang3.tuple.Pair; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Optional; public class CraftingTerminalContainer extends ItemTerminalContainer { + + public CraftingInventory craftInventory; + public CraftResultInventory craftResult; + private final PlayerEntity player; + public CraftingTerminalContainer(@Nullable ContainerType type, int id, PlayerEntity player, BlockPos pos) { super(type, id, player, pos); + this.player = player; + this.onCraftMatrixChanged(this.craftInventory); + } + + @Override + protected void addOwnSlots(PlayerEntity player) { + this.craftInventory = new WrappedCraftingInventory(this.getTile().craftItems, this, 3, 3); + this.craftResult = new CraftResultInventory(); + this.addSlot(new CraftingResultSlot(player, this.craftInventory, this.craftResult, 0, 25, 77)); + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + this.addSlot(new Slot(this.craftInventory, j + i * 3, 7 + j * 18, 18 + i * 18)); + super.addOwnSlots(player); + } + + @Override + public void onCraftMatrixChanged(IInventory inventoryIn) { + if (!this.player.world.isRemote) { + ItemStack ret = ItemStack.EMPTY; + Optional optional = this.player.world.getServer().getRecipeManager().getRecipe(IRecipeType.CRAFTING, this.craftInventory, this.player.world); + if (optional.isPresent()) + ret = optional.get().getCraftingResult(this.craftInventory); + this.craftResult.setInventorySlotContents(0, ret); + ((ServerPlayerEntity) this.player).connection.sendPacket(new SSetSlotPacket(this.windowId, 0, ret)); + } + } + + @Override + public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) { + return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> Pair.of(6 + 10, 12 + 10)); } @Override protected int getSlotXOffset() { return 65; } + + protected CraftingTerminalTileEntity getTile() { + return (CraftingTerminalTileEntity) this.tile; + } } diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/containers/CraftingTerminalGui.java b/src/main/java/de/ellpeck/prettypipes/terminal/containers/CraftingTerminalGui.java index 99d4fc9..5179206 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/containers/CraftingTerminalGui.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/containers/CraftingTerminalGui.java @@ -1,19 +1,49 @@ package de.ellpeck.prettypipes.terminal.containers; import de.ellpeck.prettypipes.PrettyPipes; +import de.ellpeck.prettypipes.packets.PacketHandler; +import de.ellpeck.prettypipes.packets.PacketRequest; +import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity; import net.minecraft.client.gui.widget.Widget; +import net.minecraft.client.gui.widget.button.Button; +import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; public class CraftingTerminalGui extends ItemTerminalGui { private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/crafting_terminal.png"); + private Button requestButton; public CraftingTerminalGui(ItemTerminalContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) { super(screenContainer, inv, titleIn); this.xSize = 256; } + @Override + protected void init() { + super.init(); + this.requestButton = this.addButton(new Button(this.guiLeft + 8, this.guiTop + 100, 50, 20, I18n.format("info." + PrettyPipes.ID + ".request"), button -> { + CraftingTerminalTileEntity tile = this.getCraftingContainer().getTile(); + for (int i = 0; i < tile.craftItems.getSlots(); i++) { + ItemStack stack = tile.getRequestedCraftItem(i); + if (stack.isEmpty()) + continue; + stack = stack.copy(); + stack.setCount(1); + PacketHandler.sendToServer(new PacketRequest(this.container.tile.getPos(), stack, 1)); + } + })); + this.requestButton.active = !this.getCraftingContainer().craftInventory.isEmpty(); + } + + @Override + public void tick() { + super.tick(); + this.requestButton.active = !this.getCraftingContainer().craftInventory.isEmpty(); + } + @Override protected ResourceLocation getTexture() { return TEXTURE; @@ -23,4 +53,8 @@ public class CraftingTerminalGui extends ItemTerminalGui { protected int getXOffset() { return 65; } + + protected CraftingTerminalContainer getCraftingContainer() { + return (CraftingTerminalContainer) this.container; + } } diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/containers/ItemTerminalContainer.java b/src/main/java/de/ellpeck/prettypipes/terminal/containers/ItemTerminalContainer.java index b74cf29..8ef080a 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/containers/ItemTerminalContainer.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/containers/ItemTerminalContainer.java @@ -31,12 +31,9 @@ public class ItemTerminalContainer extends Container { super(type, id); this.tile = Utility.getTileEntity(ItemTerminalTileEntity.class, player.world, pos); - int off = this.getSlotXOffset(); - for (int i = 0; i < 6; i++) - this.addSlot(new SlotItemHandler(this.tile.items, i, 8 + off + i % 3 * 18, 102 + i / 3 * 18)); - for (int i = 0; i < 6; i++) - this.addSlot(new SlotItemHandler(this.tile.items, i + 6, 116 + off + i % 3 * 18, 102 + i / 3 * 18)); + this.addOwnSlots(player); + int off = this.getSlotXOffset(); for (int l = 0; l < 3; ++l) for (int j1 = 0; j1 < 9; ++j1) this.addSlot(new Slot(player.inventory, j1 + l * 9 + 9, 8 + off + j1 * 18, 154 + l * 18)); @@ -44,15 +41,21 @@ public class ItemTerminalContainer extends Container { this.addSlot(new Slot(player.inventory, i1, 8 + off + i1 * 18, 212)); } + protected void addOwnSlots(PlayerEntity player) { + int off = this.getSlotXOffset(); + for (int i = 0; i < 6; i++) + this.addSlot(new SlotItemHandler(this.tile.items, i, 8 + off + i % 3 * 18, 102 + i / 3 * 18)); + for (int i = 0; i < 6; i++) + this.addSlot(new SlotItemHandler(this.tile.items, i + 6, 116 + off + i % 3 * 18, 102 + i / 3 * 18)); + } + protected int getSlotXOffset() { return 0; } @Override public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) { - return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> { - return Pair.of(6, 12); - }); + return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> Pair.of(6, 12)); } @Override diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/containers/WrappedCraftingInventory.java b/src/main/java/de/ellpeck/prettypipes/terminal/containers/WrappedCraftingInventory.java new file mode 100644 index 0000000..5c0d5b1 --- /dev/null +++ b/src/main/java/de/ellpeck/prettypipes/terminal/containers/WrappedCraftingInventory.java @@ -0,0 +1,74 @@ +package de.ellpeck.prettypipes.terminal.containers; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.CraftingInventory; +import net.minecraft.inventory.ItemStackHelper; +import net.minecraft.inventory.container.Container; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.RecipeItemHelper; +import net.minecraftforge.items.ItemStackHandler; + +public class WrappedCraftingInventory extends CraftingInventory { + + private final ItemStackHandler items; + private final Container eventHandler; + + public WrappedCraftingInventory(ItemStackHandler items, Container eventHandlerIn, int width, int height) { + super(eventHandlerIn, width, height); + this.eventHandler = eventHandlerIn; + this.items = items; + } + + @Override + public int getSizeInventory() { + return this.items.getSlots(); + } + + @Override + public boolean isEmpty() { + for (int i = 0; i < this.items.getSlots(); i++) { + if (!this.items.getStackInSlot(i).isEmpty()) + return false; + } + return true; + } + + @Override + public ItemStack getStackInSlot(int index) { + return this.items.getStackInSlot(index); + } + + @Override + public ItemStack removeStackFromSlot(int index) { + ItemStack before = this.items.getStackInSlot(index); + this.items.setStackInSlot(index, ItemStack.EMPTY); + return before; + } + + @Override + public ItemStack decrStackSize(int index, int count) { + ItemStack slotStack = this.items.getStackInSlot(index); + ItemStack ret = !slotStack.isEmpty() && count > 0 ? slotStack.split(count) : ItemStack.EMPTY; + if (!ret.isEmpty()) + this.eventHandler.onCraftMatrixChanged(this); + return ret; + } + + @Override + public void setInventorySlotContents(int index, ItemStack stack) { + this.items.setStackInSlot(index, stack); + this.eventHandler.onCraftMatrixChanged(this); + } + + @Override + public void clear() { + for (int i = 0; i < this.items.getSlots(); i++) + this.items.setStackInSlot(i, ItemStack.EMPTY); + } + + @Override + public void fillStackedContents(RecipeItemHelper helper) { + for (int i = 0; i < this.items.getSlots(); i++) + helper.accountPlainStack(this.items.getStackInSlot(i)); + } +} diff --git a/src/main/resources/assets/prettypipes/textures/gui/crafting_terminal.png b/src/main/resources/assets/prettypipes/textures/gui/crafting_terminal.png index aa5a5c3..05a3d6c 100644 Binary files a/src/main/resources/assets/prettypipes/textures/gui/crafting_terminal.png and b/src/main/resources/assets/prettypipes/textures/gui/crafting_terminal.png differ