2020-10-14 22:04:52 +02:00
|
|
|
package de.ellpeck.prettypipes.pipe.modules.craft;
|
|
|
|
|
|
|
|
import de.ellpeck.prettypipes.Registry;
|
|
|
|
import de.ellpeck.prettypipes.items.IModule;
|
|
|
|
import de.ellpeck.prettypipes.items.ModuleItem;
|
|
|
|
import de.ellpeck.prettypipes.items.ModuleTier;
|
2020-10-14 23:39:11 +02:00
|
|
|
import de.ellpeck.prettypipes.misc.ItemEqualityType;
|
|
|
|
import de.ellpeck.prettypipes.misc.ItemFilter;
|
|
|
|
import de.ellpeck.prettypipes.network.NetworkLocation;
|
|
|
|
import de.ellpeck.prettypipes.network.NetworkLock;
|
2020-10-15 01:19:22 +02:00
|
|
|
import de.ellpeck.prettypipes.network.PipeItem;
|
2020-10-14 23:39:11 +02:00
|
|
|
import de.ellpeck.prettypipes.network.PipeNetwork;
|
2020-10-14 22:04:52 +02:00
|
|
|
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
|
|
|
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
2020-10-14 23:39:11 +02:00
|
|
|
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
|
|
|
|
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
|
2020-10-14 22:04:52 +02:00
|
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
|
|
import net.minecraft.entity.player.PlayerInventory;
|
|
|
|
import net.minecraft.item.ItemStack;
|
|
|
|
import net.minecraft.nbt.CompoundNBT;
|
2020-10-15 01:19:22 +02:00
|
|
|
import net.minecraft.tileentity.TileEntity;
|
|
|
|
import net.minecraft.util.Direction;
|
2020-10-14 23:39:11 +02:00
|
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
import net.minecraft.util.math.MathHelper;
|
2020-10-15 01:19:22 +02:00
|
|
|
import net.minecraftforge.items.CapabilityItemHandler;
|
|
|
|
import net.minecraftforge.items.IItemHandler;
|
|
|
|
import net.minecraftforge.items.ItemHandlerHelper;
|
2020-10-14 22:04:52 +02:00
|
|
|
import net.minecraftforge.items.ItemStackHandler;
|
2020-10-14 23:39:11 +02:00
|
|
|
import org.apache.commons.lang3.tuple.Pair;
|
2020-10-15 01:19:22 +02:00
|
|
|
import org.apache.commons.lang3.tuple.Triple;
|
2020-10-14 22:04:52 +02:00
|
|
|
|
2020-10-14 22:30:02 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
2020-10-14 22:04:52 +02:00
|
|
|
public class CraftingModuleItem extends ModuleItem {
|
|
|
|
|
|
|
|
public final int inputSlots;
|
|
|
|
public final int outputSlots;
|
2020-10-15 01:19:22 +02:00
|
|
|
private final int speed;
|
|
|
|
private final int maxExtraction;
|
2020-10-14 22:04:52 +02:00
|
|
|
|
|
|
|
public CraftingModuleItem(String name, ModuleTier tier) {
|
|
|
|
super(name);
|
|
|
|
this.inputSlots = tier.forTier(1, 4, 9);
|
|
|
|
this.outputSlots = tier.forTier(1, 2, 4);
|
2020-10-15 01:19:22 +02:00
|
|
|
this.speed = tier.forTier(20, 10, 5);
|
|
|
|
this.maxExtraction = tier.forTier(1, 16, 32);
|
2020-10-14 22:04:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean hasContainer(ItemStack module, PipeTileEntity tile) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public AbstractPipeContainer<?> getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) {
|
|
|
|
return new CraftingModuleContainer(Registry.craftingModuleContainer, windowId, player, tile.getPos(), moduleIndex);
|
|
|
|
}
|
|
|
|
|
2020-10-14 22:30:02 +02:00
|
|
|
@Override
|
2020-10-15 01:19:22 +02:00
|
|
|
public boolean canNetworkSee(ItemStack module, PipeTileEntity tile) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void tick(ItemStack module, PipeTileEntity tile) {
|
|
|
|
if (tile.getWorld().getGameTime() % this.speed != 0 || !tile.canWork())
|
|
|
|
return;
|
2020-10-14 23:39:11 +02:00
|
|
|
PipeNetwork network = PipeNetwork.get(tile.getWorld());
|
2020-10-15 01:19:22 +02:00
|
|
|
// process crafting ingredient requests
|
|
|
|
if (!tile.craftIngredientRequests.isEmpty()) {
|
|
|
|
NetworkLock request = tile.craftIngredientRequests.remove();
|
|
|
|
Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(request.stack, true, true);
|
|
|
|
if (dest != null) {
|
|
|
|
network.requestExistingItem(request.location, tile.getPos(), dest.getLeft(), dest.getRight(), ItemEqualityType.NBT);
|
|
|
|
network.resolveNetworkLock(request);
|
|
|
|
|
|
|
|
// if we couldn't fit all items into the destination, create another request for the rest
|
|
|
|
ItemStack remain = request.stack.copy();
|
|
|
|
remain.shrink(dest.getRight().getCount());
|
|
|
|
if (!remain.isEmpty()) {
|
|
|
|
NetworkLock remainRequest = new NetworkLock(request.location, remain);
|
|
|
|
tile.craftIngredientRequests.add(remainRequest);
|
|
|
|
network.createNetworkLock(remainRequest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// pull requested crafting results from the network once they are stored
|
|
|
|
if (!tile.craftResultRequests.isEmpty()) {
|
|
|
|
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
|
|
|
|
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
|
|
|
|
for (Triple<BlockPos, BlockPos, ItemStack> request : tile.craftResultRequests) {
|
2020-10-15 01:56:42 +02:00
|
|
|
ItemStack remain = request.getRight().copy();
|
2020-10-15 01:19:22 +02:00
|
|
|
for (NetworkLocation item : items) {
|
2020-10-15 01:56:42 +02:00
|
|
|
remain = network.requestExistingItem(item, request.getLeft(), request.getMiddle(), remain, equalityTypes);
|
|
|
|
if (remain.isEmpty())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (remain.getCount() != request.getRight().getCount()) {
|
2020-10-15 01:19:22 +02:00
|
|
|
tile.craftResultRequests.remove(request);
|
|
|
|
// if we couldn't pull everything, log a new request
|
|
|
|
if (!remain.isEmpty())
|
|
|
|
tile.craftResultRequests.add(Triple.of(request.getLeft(), request.getMiddle(), remain));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-14 23:39:11 +02:00
|
|
|
|
2020-10-15 01:19:22 +02:00
|
|
|
@Override
|
|
|
|
public List<ItemStack> getCraftables(ItemStack module, PipeTileEntity tile, boolean onlyReturnPossible) {
|
2020-10-14 22:30:02 +02:00
|
|
|
ItemStackHandler output = this.getOutput(module);
|
2020-10-15 01:19:22 +02:00
|
|
|
if (!onlyReturnPossible) {
|
|
|
|
// if we only need to return the ones we *could* craft, it's easy
|
|
|
|
List<ItemStack> ret = new ArrayList<>();
|
|
|
|
for (int i = 0; i < output.getSlots(); i++) {
|
|
|
|
ItemStack stack = output.getStackInSlot(i);
|
|
|
|
if (!stack.isEmpty())
|
|
|
|
ret.add(stack);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
PipeNetwork network = PipeNetwork.get(tile.getWorld());
|
|
|
|
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
|
|
|
|
List<Pair<BlockPos, ItemStack>> craftables = network.getOrderedCraftables(tile.getPos(), true);
|
|
|
|
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
|
2020-10-14 23:39:11 +02:00
|
|
|
ItemStackHandler input = this.getInput(module);
|
|
|
|
|
|
|
|
List<ItemStack> ret = new ArrayList<>();
|
2020-10-14 22:30:02 +02:00
|
|
|
for (int i = 0; i < output.getSlots(); i++) {
|
|
|
|
ItemStack stack = output.getStackInSlot(i);
|
2020-10-14 23:39:11 +02:00
|
|
|
if (!stack.isEmpty()) {
|
2020-10-15 01:19:22 +02:00
|
|
|
// figure out how many crafting operations we can actually do with the input items we have in the network
|
2020-10-14 23:39:11 +02:00
|
|
|
int availableCrafts = CraftingTerminalTileEntity.getAvailableCrafts(tile.getWorld(), input.getSlots(), input::getStackInSlot, k -> false, s -> items, craftables, null, equalityTypes);
|
|
|
|
if (availableCrafts > 0) {
|
|
|
|
ItemStack copy = stack.copy();
|
|
|
|
copy.setCount(stack.getCount() * availableCrafts);
|
|
|
|
ret.add(copy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) {
|
|
|
|
// check if we can craft the required amount of items
|
2020-10-15 01:19:22 +02:00
|
|
|
List<ItemStack> craftables = this.getCraftables(module, tile, true);
|
2020-10-14 23:39:11 +02:00
|
|
|
int craftableAmount = craftables.stream()
|
|
|
|
.filter(c -> ItemEqualityType.compareItems(c, stack, equalityTypes))
|
|
|
|
.mapToInt(ItemStack::getCount).sum();
|
|
|
|
if (craftableAmount > 0) {
|
|
|
|
PipeNetwork network = PipeNetwork.get(tile.getWorld());
|
|
|
|
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
|
2020-10-15 01:19:22 +02:00
|
|
|
List<Pair<BlockPos, ItemStack>> allCraftables = network.getOrderedCraftables(tile.getPos(), true);
|
2020-10-14 23:39:11 +02:00
|
|
|
|
|
|
|
int resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes);
|
|
|
|
int requiredCrafts = MathHelper.ceil(stack.getCount() / (float) resultAmount);
|
|
|
|
|
|
|
|
ItemStackHandler input = this.getInput(module);
|
|
|
|
for (int i = 0; i < input.getSlots(); i++) {
|
2020-10-15 01:19:22 +02:00
|
|
|
ItemStack in = input.getStackInSlot(i);
|
2020-10-14 23:39:11 +02:00
|
|
|
if (in.isEmpty())
|
|
|
|
continue;
|
2020-10-15 01:19:22 +02:00
|
|
|
ItemStack copy = in.copy();
|
|
|
|
copy.setCount(in.getCount() * requiredCrafts);
|
|
|
|
Pair<List<NetworkLock>, ItemStack> ret = ItemTerminalTileEntity.requestItemLater(tile.getWorld(), destPipe, destInventory, copy, items, allCraftables, equalityTypes);
|
|
|
|
tile.craftIngredientRequests.addAll(ret.getLeft());
|
|
|
|
tile.craftResultRequests.add(Triple.of(destPipe, destInventory, stack));
|
2020-10-14 23:39:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ItemStack remain = stack.copy();
|
|
|
|
remain.shrink(craftableAmount);
|
|
|
|
return remain;
|
|
|
|
} else {
|
|
|
|
return stack;
|
2020-10-14 22:30:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-14 22:04:52 +02:00
|
|
|
public ItemStackHandler getInput(ItemStack module) {
|
|
|
|
ItemStackHandler handler = new ItemStackHandler(this.inputSlots);
|
|
|
|
if (module.hasTag())
|
|
|
|
handler.deserializeNBT(module.getTag().getCompound("input"));
|
|
|
|
return handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ItemStackHandler getOutput(ItemStack module) {
|
|
|
|
ItemStackHandler handler = new ItemStackHandler(this.outputSlots);
|
|
|
|
if (module.hasTag())
|
|
|
|
handler.deserializeNBT(module.getTag().getCompound("output"));
|
|
|
|
return handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void save(ItemStackHandler input, ItemStackHandler output, ItemStack module) {
|
|
|
|
CompoundNBT tag = module.getOrCreateTag();
|
|
|
|
if (input != null)
|
|
|
|
tag.put("input", input.serializeNBT());
|
|
|
|
if (output != null)
|
|
|
|
tag.put("output", output.serializeNBT());
|
|
|
|
}
|
2020-10-14 23:39:11 +02:00
|
|
|
|
|
|
|
private int getResultAmountPerCraft(ItemStack module, ItemStack stack, ItemEqualityType... equalityTypes) {
|
|
|
|
ItemStackHandler output = this.getOutput(module);
|
|
|
|
int resultAmount = 0;
|
|
|
|
for (int i = 0; i < output.getSlots(); i++) {
|
|
|
|
ItemStack out = output.getStackInSlot(i);
|
|
|
|
if (ItemEqualityType.compareItems(stack, out, equalityTypes))
|
|
|
|
resultAmount += out.getCount();
|
|
|
|
}
|
|
|
|
return resultAmount;
|
|
|
|
}
|
2020-10-14 22:04:52 +02:00
|
|
|
}
|