PrettyPipes/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalTileEntity.java

179 lines
8 KiB
Java
Raw Normal View History

2020-05-08 22:58:16 +02:00
package de.ellpeck.prettypipes.terminal;
2020-05-09 14:56:58 +02:00
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
2020-05-08 22:58:16 +02:00
import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.Registry;
2020-05-09 13:40:46 +02:00
import de.ellpeck.prettypipes.misc.EquatableItemStack;
import de.ellpeck.prettypipes.misc.ItemEqualityType;
import de.ellpeck.prettypipes.network.NetworkItem;
import de.ellpeck.prettypipes.network.NetworkLocation;
import de.ellpeck.prettypipes.network.NetworkLock;
import de.ellpeck.prettypipes.network.PipeNetwork;
2020-05-09 14:56:58 +02:00
import de.ellpeck.prettypipes.packets.PacketGhostSlot;
import de.ellpeck.prettypipes.packets.PacketHandler;
2020-05-08 22:58:16 +02:00
import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
2020-09-22 19:14:07 +02:00
import net.minecraft.block.BlockState;
2020-05-08 22:58:16 +02:00
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;
2020-05-08 22:58:16 +02:00
import net.minecraft.util.text.ITextComponent;
2020-05-09 13:40:46 +02:00
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextFormatting;
2020-05-08 22:58:16 +02:00
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.items.ItemStackHandler;
2020-05-09 13:40:46 +02:00
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.Pair;
2020-05-08 22:58:16 +02:00
2020-05-09 14:56:58 +02:00
import javax.annotation.Nonnull;
2020-05-08 22:58:16 +02:00
import javax.annotation.Nullable;
2020-05-09 14:56:58 +02:00
import java.util.*;
2020-05-08 22:58:16 +02:00
public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
2020-05-09 14:56:58 +02:00
public final ItemStackHandler craftItems = new ItemStackHandler(9) {
@Override
protected void onContentsChanged(int slot) {
for (PlayerEntity playerEntity : CraftingTerminalTileEntity.this.getLookingPlayers())
playerEntity.openContainer.onCraftMatrixChanged(null);
}
};
public final ItemStackHandler ghostItems = new ItemStackHandler(9);
2020-05-08 22:58:16 +02:00
public CraftingTerminalTileEntity() {
super(Registry.craftingTerminalTileEntity);
}
public ItemStack getRequestedCraftItem(int slot) {
2020-05-09 14:56:58 +02:00
ItemStack stack = this.craftItems.getStackInSlot(slot);
if (!stack.isEmpty())
return stack;
return this.ghostItems.getStackInSlot(slot);
}
public boolean isGhostItem(int slot) {
return this.craftItems.getStackInSlot(slot).isEmpty() && !this.ghostItems.getStackInSlot(slot).isEmpty();
}
public void setGhostItems(ListMultimap<Integer, ItemStack> stacks) {
this.updateItems();
items:
for (int i = 0; i < this.ghostItems.getSlots(); i++) {
List<ItemStack> items = stacks.get(i);
if (items.isEmpty()) {
this.ghostItems.setStackInSlot(i, ItemStack.EMPTY);
continue;
}
if (items.size() > 1) {
// set the item into the ghost slot that already has a variant of itself available in the system
for (ItemStack stack : items) {
EquatableItemStack equatable = new EquatableItemStack(stack);
NetworkItem network = this.networkItems.get(equatable);
if (network == null)
continue;
if (network.getLocations().stream().anyMatch(l -> l.getItemAmount(this.world, stack, ItemEqualityType.NBT) > 0)) {
this.ghostItems.setStackInSlot(i, stack);
continue items;
}
}
}
// if the ghost slot wasn't set, then we don't have the item in the system
// so just pick a random one to put into the slot
this.ghostItems.setStackInSlot(i, items.get(0));
}
if (!this.world.isRemote) {
ListMultimap<Integer, ItemStack> clients = ArrayListMultimap.create();
for (int i = 0; i < this.ghostItems.getSlots(); i++)
clients.put(i, this.ghostItems.getStackInSlot(i));
PacketHandler.sendToAllLoaded(this.world, this.pos, new PacketGhostSlot(this.pos, clients));
}
}
2020-05-09 13:40:46 +02:00
public void requestCraftingItems(PlayerEntity player, boolean all) {
PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_request_crafting");
this.updateItems();
2020-05-09 14:56:58 +02:00
// the highest amount we can craft with the items we have
int lowestAvailable = Integer.MAX_VALUE;
2020-05-09 13:40:46 +02:00
// this is the amount of items required for each ingredient when crafting ONE
Map<EquatableItemStack, MutableInt> requiredItems = new HashMap<>();
for (int i = 0; i < this.craftItems.getSlots(); i++) {
ItemStack requested = this.getRequestedCraftItem(i);
if (requested.isEmpty())
continue;
MutableInt amount = requiredItems.computeIfAbsent(new EquatableItemStack(requested), s -> new MutableInt());
amount.add(1);
2020-05-09 14:56:58 +02:00
int fit = requested.getMaxStackSize() - (this.isGhostItem(i) ? 0 : requested.getCount());
if (lowestAvailable > fit)
lowestAvailable = fit;
2020-05-09 13:40:46 +02:00
}
for (Map.Entry<EquatableItemStack, MutableInt> entry : requiredItems.entrySet()) {
EquatableItemStack stack = entry.getKey();
NetworkItem item = this.networkItems.get(stack);
2020-05-09 14:56:58 +02:00
// total amount of available items of this type
int available = 0;
2020-05-09 13:40:46 +02:00
if (item != null) {
for (NetworkLocation location : item.getLocations()) {
2020-05-09 16:27:49 +02:00
int amount = location.getItemAmount(this.world, stack.stack, ItemEqualityType.NBT);
if (amount <= 0)
continue;
amount -= network.getLockedAmount(location.getPos(), stack.stack, ItemEqualityType.NBT);
available += amount;
2020-05-09 13:40:46 +02:00
}
// divide the total by the amount required to get the amount that
// we have available for each crafting slot that contains this item
available /= entry.getValue().intValue();
if (available < lowestAvailable)
lowestAvailable = available;
} else {
lowestAvailable = 0;
}
2020-05-09 14:56:58 +02:00
if (available <= 0)
2020-09-22 19:14:07 +02:00
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", stack.stack.getDisplayName()).setStyle(Style.EMPTY.setFormatting(TextFormatting.RED)), UUID.randomUUID());
2020-05-09 13:40:46 +02:00
}
if (lowestAvailable > 0) {
// if we're only crafting one item, pretend we only have enough for one
if (!all)
lowestAvailable = 1;
for (int i = 0; i < this.craftItems.getSlots(); i++) {
ItemStack requested = this.getRequestedCraftItem(i);
if (requested.isEmpty())
continue;
requested = requested.copy();
requested.setCount(lowestAvailable);
this.requestItemImpl(requested);
}
2020-09-22 19:14:07 +02:00
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".sending_ingredients", lowestAvailable).setStyle(Style.EMPTY.setFormatting(TextFormatting.GREEN)), UUID.randomUUID());
2020-05-09 13:40:46 +02:00
}
network.endProfile();
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.put("craft_items", this.craftItems.serializeNBT());
return super.write(compound);
}
@Override
2020-09-22 19:14:07 +02:00
public void read(BlockState state, CompoundNBT compound) {
this.craftItems.deserializeNBT(compound.getCompound("craft_items"));
2020-09-22 19:14:07 +02:00
super.read(state, compound);
}
2020-05-08 22:58:16 +02:00
@Override
public ITextComponent getDisplayName() {
return new TranslationTextComponent("container." + PrettyPipes.ID + ".crafting_terminal");
}
@Nullable
@Override
public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
return new CraftingTerminalContainer(Registry.craftingTerminalContainer, window, player, this.pos);
}
}