finished the crafting terminal!

This commit is contained in:
Ellpeck 2020-05-09 13:40:46 +02:00
parent 8bd5a0cae3
commit f9c5ea86f7
6 changed files with 115 additions and 26 deletions

View file

@ -8,6 +8,7 @@ import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer;
import de.ellpeck.prettypipes.pipe.PipeTileEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem; import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem;
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity; import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -109,6 +110,11 @@ public class PacketButton {
STACK_SIZE_AMOUNT((pos, data, player) -> { STACK_SIZE_AMOUNT((pos, data, player) -> {
AbstractPipeContainer<?> container = (AbstractPipeContainer<?>) player.openContainer; AbstractPipeContainer<?> container = (AbstractPipeContainer<?>) player.openContainer;
StackSizeModuleItem.setMaxStackSize(container.moduleStack, data[0]); StackSizeModuleItem.setMaxStackSize(container.moduleStack, data[0]);
}),
CRAFT_TERMINAL_REQUEST((pos, data, player) -> {
CraftingTerminalTileEntity tile = Utility.getTileEntity(CraftingTerminalTileEntity.class, player.world, pos);
boolean all = data[0] > 0;
tile.requestCraftingItems(player, all);
}); });
public final TriConsumer<BlockPos, int[], PlayerEntity> action; public final TriConsumer<BlockPos, int[], PlayerEntity> action;

View file

@ -27,20 +27,23 @@ public class CraftingTerminalBlock extends ItemTerminalBlock {
BlockPos pos = pipePos.offset(direction); BlockPos pos = pipePos.offset(direction);
CraftingTerminalTileEntity tile = Utility.getTileEntity(CraftingTerminalTileEntity.class, world, pos); CraftingTerminalTileEntity tile = Utility.getTileEntity(CraftingTerminalTileEntity.class, world, pos);
if (tile != null) { 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; ItemStack remain = item.stack;
if (lowestFitting >= 0) { int lowestFitting = -1;
remain = tile.craftItems.insertItem(lowestFitting, item.stack, false); do {
if (remain.isEmpty()) for (int i = 0; i < tile.craftItems.getSlots(); i++) {
return ItemStack.EMPTY; ItemStack stack = tile.getRequestedCraftItem(i);
if (!ItemHandlerHelper.canItemStacksStackRelaxed(stack, remain))
continue;
if (lowestFitting < 0 || stack.getCount() < tile.getRequestedCraftItem(lowestFitting).getCount())
lowestFitting = i;
}
if (lowestFitting >= 0) {
remain = tile.craftItems.insertItem(lowestFitting, remain, false);
if (remain.isEmpty())
return ItemStack.EMPTY;
}
} }
while (lowestFitting >= 0);
return ItemHandlerHelper.insertItemStacked(tile.items, remain, false); return ItemHandlerHelper.insertItemStacked(tile.items, remain, false);
} }
return item.stack; return item.stack;

View file

@ -2,6 +2,12 @@ package de.ellpeck.prettypipes.terminal;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.Registry;
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;
import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer; import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -10,10 +16,18 @@ import net.minecraft.inventory.container.Container;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CraftingTerminalTileEntity extends ItemTerminalTileEntity { public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
@ -28,6 +42,68 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
return this.craftItems.getStackInSlot(slot); return this.craftItems.getStackInSlot(slot);
} }
public void requestCraftingItems(PlayerEntity player, boolean all) {
PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_request_crafting");
this.updateItems();
// 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);
}
// the highest amount we can craft with the items we have
int lowestAvailable = Integer.MAX_VALUE;
for (Map.Entry<EquatableItemStack, MutableInt> entry : requiredItems.entrySet()) {
EquatableItemStack stack = entry.getKey();
NetworkItem item = this.networkItems.get(stack);
if (item != null) {
// total amount of available items of this type
int available = 0;
for (NetworkLocation location : item.getLocations()) {
for (int slot : location.getStackSlots(this.world, stack.stack, ItemEqualityType.NBT)) {
ItemStack inSlot = location.getItemHandler(this.world).extractItem(slot, Integer.MAX_VALUE, true);
if (inSlot.isEmpty())
continue;
inSlot.shrink(network.getLockedAmount(location.getPos(), slot));
available += inSlot.getCount();
}
}
// 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();
int fit = stack.stack.getMaxStackSize() - stack.stack.getCount();
if (available > fit)
available = fit;
if (available < lowestAvailable)
lowestAvailable = available;
} else {
lowestAvailable = 0;
}
if (lowestAvailable <= 0)
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", stack.stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.RED)));
}
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);
}
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".sending_ingredients", lowestAvailable).setStyle(new Style().setColor(TextFormatting.GREEN)));
}
network.endProfile();
}
@Override @Override
public CompoundNBT write(CompoundNBT compound) { public CompoundNBT write(CompoundNBT compound) {
compound.put("craft_items", this.craftItems.serializeNBT()); compound.put("craft_items", this.craftItems.serializeNBT());

View file

@ -138,8 +138,19 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
public void requestItem(PlayerEntity player, ItemStack stack) { public void requestItem(PlayerEntity player, ItemStack stack) {
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);
this.updateItems(); this.updateItems();
int requested = this.requestItemImpl(stack);
if (requested > 0) {
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".sending", requested, stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.GREEN)));
} else {
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.RED)));
}
network.endProfile();
}
protected int requestItemImpl(ItemStack stack) {
PipeNetwork network = PipeNetwork.get(this.world);
EquatableItemStack equatable = new EquatableItemStack(stack);
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();
@ -161,11 +172,9 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
} }
} }
} }
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".sending", stack.getCount() - remain, stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.GREEN))); return stack.getCount() - remain;
} else {
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.RED)));
} }
network.endProfile(); return 0;
} }
private PlayerEntity[] getLookingPlayers() { private PlayerEntity[] getLookingPlayers() {

View file

@ -1,6 +1,7 @@
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.PacketButton;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.packets.PacketRequest; import de.ellpeck.prettypipes.packets.PacketRequest;
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity; import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
@ -25,15 +26,8 @@ public class CraftingTerminalGui extends ItemTerminalGui {
protected void init() { protected void init() {
super.init(); super.init();
this.requestButton = this.addButton(new Button(this.guiLeft + 8, this.guiTop + 100, 50, 20, I18n.format("info." + PrettyPipes.ID + ".request"), button -> { 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(); int all = hasShiftDown() ? 1 : 0;
for (int i = 0; i < tile.craftItems.getSlots(); i++) { PacketHandler.sendToServer(new PacketButton(this.container.tile.getPos(), PacketButton.ButtonResult.CRAFT_TERMINAL_REQUEST, all));
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(); this.requestButton.active = !this.getCraftingContainer().craftInventory.isEmpty();
} }

View file

@ -50,6 +50,7 @@
"info.prettypipes.request": "Request", "info.prettypipes.request": "Request",
"info.prettypipes.not_found": "%s not found", "info.prettypipes.not_found": "%s not found",
"info.prettypipes.sending": "Sending %s %s", "info.prettypipes.sending": "Sending %s %s",
"info.prettypipes.sending_ingredients": "Sending %s sets of ingredients",
"info.prettypipes.order": "Order by %s", "info.prettypipes.order": "Order by %s",
"info.prettypipes.order.amount": "Amount", "info.prettypipes.order.amount": "Amount",
"info.prettypipes.order.name": "Name", "info.prettypipes.order.name": "Name",