more crafting terminal work + network locks

This commit is contained in:
Ellpeck 2020-05-09 01:00:59 +02:00
parent 67e7da2b73
commit ccc981fee3
17 changed files with 330 additions and 60 deletions

View file

@ -76,7 +76,7 @@ public class ItemFilter extends ItemStackHandler {
} else if (id == 1 && this.canPopulateFromInventories) { } else if (id == 1 && this.canPopulateFromInventories) {
// populate filter from inventories // populate filter from inventories
for (Direction direction : Direction.values()) { for (Direction direction : Direction.values()) {
IItemHandler handler = this.pipe.getItemHandler(direction, false); IItemHandler handler = this.pipe.getItemHandler(direction, null);
if (handler == null) if (handler == null)
continue; continue;
for (int i = 0; i < handler.getSlots(); i++) { for (int i = 0; i < handler.getSlots(); i++) {

View file

@ -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;
}
}

View file

@ -1,6 +1,7 @@
package de.ellpeck.prettypipes.network; package de.ellpeck.prettypipes.network;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
import de.ellpeck.prettypipes.pipe.PipeTileEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.ILiquidContainer; import net.minecraft.block.ILiquidContainer;
@ -172,10 +173,13 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
private ItemStack store(PipeTileEntity currPipe) { private ItemStack store(PipeTileEntity currPipe) {
Direction dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe()); Direction dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe());
IItemHandler handler = currPipe.getItemHandler(dir, true); IPipeConnectable connectable = currPipe.getPipeConnectable(dir);
if (handler == null) if (connectable != null)
return this.stack; return connectable.insertItem(currPipe.getWorld(), currPipe.getPos(), dir, this);
return ItemHandlerHelper.insertItemStacked(handler, this.stack, false); 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) { private PipeTileEntity getNextTile(PipeTileEntity currPipe, boolean progress) {

View file

@ -50,6 +50,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
private final Map<BlockPos, List<BlockPos>> nodeToConnectedNodes = new HashMap<>(); private final Map<BlockPos, List<BlockPos>> nodeToConnectedNodes = new HashMap<>();
private final Map<BlockPos, PipeTileEntity> tileCache = new HashMap<>(); private final Map<BlockPos, PipeTileEntity> tileCache = new HashMap<>();
private final ListMultimap<BlockPos, PipeItem> pipeItems = ArrayListMultimap.create(); private final ListMultimap<BlockPos, PipeItem> pipeItems = ArrayListMultimap.create();
private final ListMultimap<BlockPos, NetworkLock> networkLocks = ArrayListMultimap.create();
private final World world; private final World world;
public PipeNetwork(World world) { public PipeNetwork(World world) {
@ -189,7 +190,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
if (!pipe.canNetworkSee()) if (!pipe.canNetworkSee())
continue; continue;
for (Direction dir : Direction.values()) { for (Direction dir : Direction.values()) {
IItemHandler handler = pipe.getItemHandler(dir, false); IItemHandler handler = pipe.getItemHandler(dir, null);
if (handler == null) if (handler == null)
continue; continue;
// check if this handler already exists (double-connected pipes, double chests etc.) // check if this handler already exists (double-connected pipes, double chests etc.)
@ -210,6 +211,24 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
return info; 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<NetworkLock> 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) { private void refreshNode(BlockPos pos, BlockState state) {
this.startProfile("refresh_node"); this.startProfile("refresh_node");
this.graph.removeAllEdges(new ArrayList<>(this.graph.edgesOf(pos))); this.graph.removeAllEdges(new ArrayList<>(this.graph.edgesOf(pos)));

View file

@ -1,6 +1,8 @@
package de.ellpeck.prettypipes.pipe; package de.ellpeck.prettypipes.pipe;
import de.ellpeck.prettypipes.network.PipeItem;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -8,9 +10,13 @@ import net.minecraftforge.items.IItemHandler;
public interface IPipeConnectable { 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; return null;
} }
default ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) {
return item.stack;
}
} }

View file

@ -72,7 +72,7 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos); PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos);
if (tile == null) if (tile == null)
return ActionResultType.PASS; return ActionResultType.PASS;
if (!tile.isConnectedInventory(false)) if (!tile.isConnectedInventory())
return ActionResultType.PASS; return ActionResultType.PASS;
if (!worldIn.isRemote) if (!worldIn.isRemote)
NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos); NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos);
@ -161,7 +161,7 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
BlockState offState = world.getBlockState(offset); BlockState offState = world.getBlockState(offset);
Block block = offState.getBlock(); Block block = offState.getBlock();
if (block instanceof IPipeConnectable) 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); TileEntity tile = world.getTileEntity(offset);
if (tile != null) { if (tile != null) {
IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()).orElse(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) { public static void onStateChanged(World world, BlockPos pos, BlockState newState) {
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, world, pos); PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, world, pos);
if (tile != null && !tile.isConnectedInventory(false)) if (tile != null && !tile.isConnectedInventory())
Utility.dropInventory(tile, tile.modules); Utility.dropInventory(tile, tile.modules);
PipeNetwork network = PipeNetwork.get(world); PipeNetwork network = PipeNetwork.get(world);
@ -252,8 +252,9 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
} }
@Override @Override
public ConnectionType getConnectionType(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction) { public ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction) {
if (state.get(DIRECTIONS.get(direction)) == ConnectionType.BLOCKED) BlockState state = world.getBlockState(pipePos.offset(direction));
if (state.get(DIRECTIONS.get(direction.getOpposite())) == ConnectionType.BLOCKED)
return ConnectionType.BLOCKED; return ConnectionType.BLOCKED;
return ConnectionType.CONNECTED; return ConnectionType.CONNECTED;
} }

View file

@ -139,7 +139,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack))) if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack)))
return null; return null;
for (Direction dir : Direction.values()) { for (Direction dir : Direction.values()) {
IItemHandler handler = this.getItemHandler(dir, force); IItemHandler handler = this.getItemHandler(dir, null);
if (handler == null) if (handler == null)
continue; continue;
if (!ItemHandlerHelper.insertItem(handler, stack, true).isEmpty()) 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)); 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)) if (!this.isConnected(dir))
return null; return null;
BlockPos pos = this.pos.offset(dir); BlockPos pos = this.pos.offset(dir);
@ -208,21 +208,25 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
if (handler != null) if (handler != null)
return handler; return handler;
} }
BlockState state = this.world.getBlockState(pos); IPipeConnectable connectable = this.getPipeConnectable(dir);
if (state.getBlock() instanceof IPipeConnectable) { if (connectable != null)
IItemHandler handler = ((IPipeConnectable) state.getBlock()).getItemHandler(this.world, pos, state, this.pos, dir, force); return connectable.getItemHandler(this.world, this.pos, dir, item);
if (handler != null)
return handler;
}
return null; return null;
} }
public boolean isConnectedInventory(Direction dir, boolean force) { public IPipeConnectable getPipeConnectable(Direction dir) {
return this.getItemHandler(dir, force) != null; 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) { public boolean isConnectedInventory(Direction dir) {
return Arrays.stream(Direction.values()).anyMatch(dir -> this.isConnectedInventory(dir, force)); return this.getItemHandler(dir, null) != null;
}
public boolean isConnectedInventory() {
return Arrays.stream(Direction.values()).anyMatch(this::isConnectedInventory);
} }
public boolean canNetworkSee() { public boolean canNetworkSee() {

View file

@ -39,7 +39,7 @@ public class ExtractionModuleItem extends ModuleItem {
PipeNetwork network = PipeNetwork.get(tile.getWorld()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
for (Direction dir : Direction.values()) { for (Direction dir : Direction.values()) {
IItemHandler handler = tile.getItemHandler(dir, false); IItemHandler handler = tile.getItemHandler(dir, null);
if (handler == null) if (handler == null)
continue; continue;
for (int j = 0; j < handler.getSlots(); j++) { for (int j = 0; j < handler.getSlots(); j++) {

View file

@ -1,9 +1,16 @@
package de.ellpeck.prettypipes.terminal; package de.ellpeck.prettypipes.terminal;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui; import de.ellpeck.prettypipes.Utility;
import net.minecraft.block.ContainerBlock; 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.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader; 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; import javax.annotation.Nullable;
@ -14,4 +21,29 @@ public class CraftingTerminalBlock extends ItemTerminalBlock {
public TileEntity createNewTileEntity(IBlockReader worldIn) { public TileEntity createNewTileEntity(IBlockReader worldIn) {
return new CraftingTerminalTileEntity(); 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;
}
} }

View file

@ -7,17 +7,39 @@ import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container; 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.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.items.ItemStackHandler;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class CraftingTerminalTileEntity extends ItemTerminalTileEntity { public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
public final ItemStackHandler craftItems = new ItemStackHandler(9);
public CraftingTerminalTileEntity() { public CraftingTerminalTileEntity() {
super(Registry.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 @Override
public ITextComponent getDisplayName() { public ITextComponent getDisplayName() {
return new TranslationTextComponent("container." + PrettyPipes.ID + ".crafting_terminal"); return new TranslationTextComponent("container." + PrettyPipes.ID + ".crafting_terminal");

View file

@ -25,6 +25,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
@ -63,18 +64,17 @@ public class ItemTerminalBlock extends ContainerBlock implements IPipeConnectabl
} }
@Override @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; return ConnectionType.CONNECTED;
} }
@Override @Override
public IItemHandler getItemHandler(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction, boolean force) { public ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) {
if (force) { BlockPos pos = pipePos.offset(direction);
ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, world, pos); ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, world, pos);
if (tile != null) if (tile != null)
return tile.items; return ItemHandlerHelper.insertItemStacked(tile.items, item.stack, false);
} return item.stack;
return null;
} }
@Override @Override

View file

@ -6,10 +6,7 @@ import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.misc.EquatableItemStack; import de.ellpeck.prettypipes.misc.EquatableItemStack;
import de.ellpeck.prettypipes.misc.ItemEqualityType; import de.ellpeck.prettypipes.misc.ItemEqualityType;
import de.ellpeck.prettypipes.misc.ItemOrder; import de.ellpeck.prettypipes.misc.ItemOrder;
import de.ellpeck.prettypipes.network.NetworkItem; import de.ellpeck.prettypipes.network.*;
import de.ellpeck.prettypipes.network.NetworkLocation;
import de.ellpeck.prettypipes.network.PipeItem;
import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.packets.PacketNetworkItems; import de.ellpeck.prettypipes.packets.PacketNetworkItems;
import de.ellpeck.prettypipes.pipe.PipeTileEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
@ -50,7 +47,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
} }
}; };
public Map<EquatableItemStack, NetworkItem> networkItems; public Map<EquatableItemStack, NetworkItem> networkItems;
private final Queue<Triple<NetworkLocation, Integer, Integer>> pendingRequests = new ArrayDeque<>(); private final Queue<NetworkLock> pendingRequests = new ArrayDeque<>();
protected ItemTerminalTileEntity(TileEntityType<?> tileEntityTypeIn) { protected ItemTerminalTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn); super(tileEntityTypeIn);
@ -82,13 +79,11 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
} }
if (!this.pendingRequests.isEmpty()) { if (!this.pendingRequests.isEmpty()) {
Triple<NetworkLocation, Integer, Integer> request = this.pendingRequests.remove(); NetworkLock request = this.pendingRequests.remove();
NetworkLocation location = request.getLeft(); network.resolveNetworkLock(request);
int slot = request.getMiddle(); ItemStack extracted = request.location.handler.extractItem(request.slot, request.amount, true);
int amount = request.getRight(); if (network.routeItemToLocation(request.location.pipePos, request.location.pos, pipe.getPos(), this.pos, speed -> new PipeItem(extracted, speed))) {
ItemStack extracted = location.handler.extractItem(slot, amount, true); request.location.handler.extractItem(request.slot, extracted.getCount(), false);
if (network.routeItemToLocation(location.pipePos, location.pos, pipe.getPos(), this.pos, speed -> new PipeItem(extracted, speed))) {
location.handler.extractItem(slot, extracted.getCount(), false);
update = true; update = true;
} }
} }
@ -132,16 +127,23 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
PipeNetwork network = PipeNetwork.get(this.world); PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_request_item"); network.startProfile("terminal_request_item");
EquatableItemStack equatable = new EquatableItemStack(stack); EquatableItemStack equatable = new EquatableItemStack(stack);
this.updateItems();
NetworkItem item = this.networkItems.get(equatable); NetworkItem item = this.networkItems.get(equatable);
if (item != null) { if (item != null) {
int remain = stack.getCount(); int remain = stack.getCount();
locations: locations:
for (NetworkLocation location : item.getLocations()) { for (NetworkLocation location : item.getLocations()) {
for (int slot : location.getStackSlots(stack, ItemEqualityType.NBT)) { for (int slot : location.getStackSlots(stack, ItemEqualityType.NBT)) {
ItemStack extracted = location.handler.extractItem(slot, remain, true); ItemStack inSlot = location.handler.extractItem(slot, Integer.MAX_VALUE, true);
if (!extracted.isEmpty()) { if (inSlot.isEmpty())
this.pendingRequests.add(Triple.of(location, slot, extracted.getCount())); continue;
remain -= extracted.getCount(); 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) if (remain <= 0)
break locations; break locations;
} }

View file

@ -1,19 +1,74 @@
package de.ellpeck.prettypipes.terminal.containers; 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.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.ContainerType;
import net.minecraft.inventory.container.CraftingResultSlot;
import net.minecraft.inventory.container.Slot; 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.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 javax.annotation.Nullable;
import java.util.Optional;
public class CraftingTerminalContainer extends ItemTerminalContainer { 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) { public CraftingTerminalContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos) {
super(type, id, player, 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<ICraftingRecipe> 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 @Override
protected int getSlotXOffset() { protected int getSlotXOffset() {
return 65; return 65;
} }
protected CraftingTerminalTileEntity getTile() {
return (CraftingTerminalTileEntity) this.tile;
}
} }

View file

@ -1,19 +1,49 @@
package de.ellpeck.prettypipes.terminal.containers; package de.ellpeck.prettypipes.terminal.containers;
import de.ellpeck.prettypipes.PrettyPipes; 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.Widget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
public class CraftingTerminalGui extends ItemTerminalGui { public class CraftingTerminalGui extends ItemTerminalGui {
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/crafting_terminal.png"); 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) { public CraftingTerminalGui(ItemTerminalContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
this.xSize = 256; 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 @Override
protected ResourceLocation getTexture() { protected ResourceLocation getTexture() {
return TEXTURE; return TEXTURE;
@ -23,4 +53,8 @@ public class CraftingTerminalGui extends ItemTerminalGui {
protected int getXOffset() { protected int getXOffset() {
return 65; return 65;
} }
protected CraftingTerminalContainer getCraftingContainer() {
return (CraftingTerminalContainer) this.container;
}
} }

View file

@ -31,12 +31,9 @@ public class ItemTerminalContainer extends Container {
super(type, id); super(type, id);
this.tile = Utility.getTileEntity(ItemTerminalTileEntity.class, player.world, pos); this.tile = Utility.getTileEntity(ItemTerminalTileEntity.class, player.world, pos);
int off = this.getSlotXOffset(); this.addOwnSlots(player);
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));
int off = this.getSlotXOffset();
for (int l = 0; l < 3; ++l) for (int l = 0; l < 3; ++l)
for (int j1 = 0; j1 < 9; ++j1) for (int j1 = 0; j1 < 9; ++j1)
this.addSlot(new Slot(player.inventory, j1 + l * 9 + 9, 8 + off + j1 * 18, 154 + l * 18)); 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)); 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() { protected int getSlotXOffset() {
return 0; return 0;
} }
@Override @Override
public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) { public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) {
return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> { return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> Pair.of(6, 12));
return Pair.of(6, 12);
});
} }
@Override @Override

View file

@ -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));
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB