unify equality types and add jei transfer

This commit is contained in:
Ell 2020-10-15 06:07:06 +02:00
parent 70c1e82db1
commit 6ae511e485
10 changed files with 160 additions and 15 deletions

View file

@ -0,0 +1,52 @@
package de.ellpeck.prettypipes.compat.jei;
import de.ellpeck.prettypipes.misc.ItemEqualityType;
import de.ellpeck.prettypipes.packets.PacketCraftingModuleTransfer;
import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleContainer;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.ingredient.IGuiIngredient;
import mezz.jei.api.recipe.transfer.IRecipeTransferError;
import mezz.jei.api.recipe.transfer.IRecipeTransferHandler;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class CraftingModuleTransferHandler implements IRecipeTransferHandler<CraftingModuleContainer> {
@Override
public Class<CraftingModuleContainer> getContainerClass() {
return CraftingModuleContainer.class;
}
@Override
public IRecipeTransferError transferRecipe(CraftingModuleContainer container, Object recipe, IRecipeLayout recipeLayout, PlayerEntity player, boolean maxTransfer, boolean doTransfer) {
if (!doTransfer)
return null;
Map<Integer, ? extends IGuiIngredient<ItemStack>> ings = recipeLayout.getItemStacks().getGuiIngredients();
List<ItemStack> inputs = new ArrayList<>();
List<ItemStack> outputs = new ArrayList<>();
for (Map.Entry<Integer, ? extends IGuiIngredient<ItemStack>> entry : ings.entrySet()) {
List<ItemStack> allIngredients = entry.getValue().getAllIngredients();
if (allIngredients.isEmpty())
continue;
ItemStack remain = allIngredients.get(0).copy();
List<ItemStack> toAdd = entry.getValue().isInput() ? inputs : outputs;
for (ItemStack stack : toAdd) {
if (ItemEqualityType.compareItems(stack, remain)) {
int fits = Math.min(stack.getMaxStackSize() - stack.getCount(), remain.getCount());
stack.grow(fits);
remain.shrink(fits);
if (remain.isEmpty())
break;
}
}
if (!remain.isEmpty())
toAdd.add(remain);
}
PacketHandler.sendToServer(new PacketCraftingModuleTransfer(inputs, outputs));
return null;
}
}

View file

@ -53,6 +53,7 @@ public class JEIPrettyPipesPlugin implements IModPlugin {
@Override @Override
public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) {
registration.addRecipeTransferHandler(new CraftingTerminalTransferHandler(), VanillaRecipeCategoryUid.CRAFTING); registration.addRecipeTransferHandler(new CraftingTerminalTransferHandler(), VanillaRecipeCategoryUid.CRAFTING);
registration.addUniversalRecipeTransferHandler(new CraftingModuleTransferHandler());
} }
@SubscribeEvent @SubscribeEvent

View file

@ -37,7 +37,7 @@ public interface IModule {
List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile); List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile);
int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes); int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack);
ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes); ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack);
} }

View file

@ -84,12 +84,12 @@ public abstract class ModuleItem extends Item implements IModule {
} }
@Override @Override
public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) { public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
return 0; return 0;
} }
@Override @Override
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) { public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
return stack; return stack;
} }
} }

View file

@ -204,7 +204,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
PipeTileEntity pipe = this.getPipe(craftable.getLeft()); PipeTileEntity pipe = this.getPipe(craftable.getLeft());
if (pipe == null) if (pipe == null)
continue; continue;
stack = pipe.craft(destPipe, unavailableConsumer, stack, equalityTypes); stack = pipe.craft(destPipe, unavailableConsumer, stack);
if (stack.isEmpty()) if (stack.isEmpty())
break; break;
} }
@ -274,7 +274,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
continue; continue;
PipeTileEntity pipe = this.getPipe(pair.getLeft()); PipeTileEntity pipe = this.getPipe(pair.getLeft());
if (pipe != null) if (pipe != null)
total += pipe.getCraftableAmount(unavailableConsumer, stack, equalityTypes); total += pipe.getCraftableAmount(unavailableConsumer, stack);
} }
return total; return total;
} }

View file

@ -0,0 +1,88 @@
package de.ellpeck.prettypipes.packets;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.misc.FilterSlot;
import de.ellpeck.prettypipes.misc.ItemEqualityType;
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleContainer;
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleItem;
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class PacketCraftingModuleTransfer {
private List<ItemStack> inputs;
private List<ItemStack> outputs;
public PacketCraftingModuleTransfer(List<ItemStack> inputs, List<ItemStack> outputs) {
this.inputs = inputs;
this.outputs = outputs;
}
private PacketCraftingModuleTransfer() {
}
public static PacketCraftingModuleTransfer fromBytes(PacketBuffer buf) {
PacketCraftingModuleTransfer packet = new PacketCraftingModuleTransfer();
packet.inputs = new ArrayList<>();
for (int i = buf.readInt(); i > 0; i--)
packet.inputs.add(buf.readItemStack());
packet.outputs = new ArrayList<>();
for (int i = buf.readInt(); i > 0; i--)
packet.outputs.add(buf.readItemStack());
return packet;
}
public static void toBytes(PacketCraftingModuleTransfer packet, PacketBuffer buf) {
buf.writeInt(packet.inputs.size());
for (ItemStack stack : packet.inputs)
buf.writeItemStack(stack);
buf.writeInt(packet.outputs.size());
for (ItemStack stack : packet.outputs)
buf.writeItemStack(stack);
}
@SuppressWarnings("Convert2Lambda")
public static void onMessage(PacketCraftingModuleTransfer message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(new Runnable() {
@Override
public void run() {
PlayerEntity player = ctx.get().getSender();
if (player.openContainer instanceof CraftingModuleContainer) {
CraftingModuleContainer container = (CraftingModuleContainer) player.openContainer;
copy(container.input, message.inputs);
copy(container.output, message.outputs);
container.modified = true;
container.detectAndSendChanges();
}
}
});
ctx.get().setPacketHandled(true);
}
private static void copy(ItemStackHandler container, List<ItemStack> contents) {
for (int i = 0; i < container.getSlots(); i++)
container.setStackInSlot(i, ItemStack.EMPTY);
for (ItemStack stack : contents)
ItemHandlerHelper.insertItem(container, stack, false);
}
}

View file

@ -23,6 +23,7 @@ public final class PacketHandler {
network.registerMessage(2, PacketNetworkItems.class, PacketNetworkItems::toBytes, PacketNetworkItems::fromBytes, PacketNetworkItems::onMessage); network.registerMessage(2, PacketNetworkItems.class, PacketNetworkItems::toBytes, PacketNetworkItems::fromBytes, PacketNetworkItems::onMessage);
network.registerMessage(3, PacketRequest.class, PacketRequest::toBytes, PacketRequest::fromBytes, PacketRequest::onMessage); network.registerMessage(3, PacketRequest.class, PacketRequest::toBytes, PacketRequest::fromBytes, PacketRequest::onMessage);
network.registerMessage(4, PacketGhostSlot.class, PacketGhostSlot::toBytes, PacketGhostSlot::fromBytes, PacketGhostSlot::onMessage); network.registerMessage(4, PacketGhostSlot.class, PacketGhostSlot::toBytes, PacketGhostSlot::fromBytes, PacketGhostSlot::onMessage);
network.registerMessage(5, PacketCraftingModuleTransfer.class, PacketCraftingModuleTransfer::toBytes, PacketCraftingModuleTransfer::fromBytes, PacketCraftingModuleTransfer::onMessage);
} }
public static void sendToAllLoaded(World world, BlockPos pos, Object message) { public static void sendToAllLoaded(World world, BlockPos pos, Object message) {

View file

@ -265,17 +265,17 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public int getCraftableAmount(Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) { public int getCraftableAmount(Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
return this.streamModules() return this.streamModules()
.mapToInt(m -> m.getRight().getCraftableAmount(m.getLeft(), this, unavailableConsumer, stack, equalityTypes)) .mapToInt(m -> m.getRight().getCraftableAmount(m.getLeft(), this, unavailableConsumer, stack))
.sum(); .sum();
} }
public ItemStack craft(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) { public ItemStack craft(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
Iterator<Pair<ItemStack, IModule>> modules = this.streamModules().iterator(); Iterator<Pair<ItemStack, IModule>> modules = this.streamModules().iterator();
while (modules.hasNext()) { while (modules.hasNext()) {
Pair<ItemStack, IModule> module = modules.next(); Pair<ItemStack, IModule> module = modules.next();
stack = module.getRight().craft(module.getLeft(), this, destPipe, unavailableConsumer, stack, equalityTypes); stack = module.getRight().craft(module.getLeft(), this, destPipe, unavailableConsumer, stack);
if (stack.isEmpty()) if (stack.isEmpty())
break; break;
} }

View file

@ -11,7 +11,7 @@ public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModul
public ItemStackHandler input; public ItemStackHandler input;
public ItemStackHandler output; public ItemStackHandler output;
private boolean modified; public boolean modified;
public CraftingModuleContainer(ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) { public CraftingModuleContainer(ContainerType<?> type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) {
super(type, id, player, pos, moduleIndex); super(type, id, player, pos, moduleIndex);

View file

@ -81,9 +81,10 @@ public class CraftingModuleItem extends ModuleItem {
if (!tile.craftIngredientRequests.isEmpty()) { if (!tile.craftIngredientRequests.isEmpty()) {
network.startProfile("crafting_ingredients"); network.startProfile("crafting_ingredients");
NetworkLock request = tile.craftIngredientRequests.peek(); NetworkLock request = tile.craftIngredientRequests.peek();
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(request.stack, true, true); Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(request.stack, true, true);
if (dest != null) { if (dest != null) {
ItemStack requestRemain = network.requestExistingItem(request.location, tile.getPos(), dest.getLeft(), request, dest.getRight(), ItemEqualityType.NBT); ItemStack requestRemain = network.requestExistingItem(request.location, tile.getPos(), dest.getLeft(), request, dest.getRight(),equalityTypes);
network.resolveNetworkLock(request); network.resolveNetworkLock(request);
tile.craftIngredientRequests.remove(); tile.craftIngredientRequests.remove();
@ -158,9 +159,10 @@ public class CraftingModuleItem extends ModuleItem {
} }
@Override @Override
public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) { public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
PipeNetwork network = PipeNetwork.get(tile.getWorld()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos()); List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
ItemStackHandler input = this.getInput(module); ItemStackHandler input = this.getInput(module);
int craftable = 0; int craftable = 0;
@ -178,15 +180,16 @@ public class CraftingModuleItem extends ModuleItem {
} }
@Override @Override
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) { public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack) {
// check if we can craft the required amount of items // check if we can craft the required amount of items
int craftableAmount = this.getCraftableAmount(module, tile, unavailableConsumer, stack, equalityTypes); int craftableAmount = this.getCraftableAmount(module, tile, unavailableConsumer, stack);
if (craftableAmount <= 0) if (craftableAmount <= 0)
return stack; return stack;
PipeNetwork network = PipeNetwork.get(tile.getWorld()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos()); List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
int resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes); int resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes);
int requiredCrafts = MathHelper.ceil(stack.getCount() / (float) resultAmount); int requiredCrafts = MathHelper.ceil(stack.getCount() / (float) resultAmount);
int toCraft = Math.min(craftableAmount, requiredCrafts); int toCraft = Math.min(craftableAmount, requiredCrafts);