Update Auto crafting table to use the better code from the rolling machine, should fix some issues.
This commit is contained in:
parent
c1343cdc26
commit
3ca9347212
2 changed files with 180 additions and 187 deletions
|
@ -82,7 +82,7 @@ public class GuiAutoCrafting extends GuiBase {
|
|||
@Override
|
||||
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
|
||||
super.drawGuiContainerForegroundLayer(mouseX, mouseY);
|
||||
IRecipe recipe = tileAutoCraftingTable.getIRecipe();
|
||||
IRecipe recipe = tileAutoCraftingTable.findMatchingRecipe(tileAutoCraftingTable.getCraftingInventory());
|
||||
if (recipe != null) {
|
||||
renderItemStack(recipe.getRecipeOutput(), 95, 42);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import net.minecraft.item.crafting.IRecipe;
|
|||
import net.minecraft.item.crafting.Ingredient;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import reborncore.api.IToolDrop;
|
||||
import reborncore.api.tile.IInventoryProvider;
|
||||
|
@ -47,12 +46,13 @@ import reborncore.client.containerBuilder.IContainerProvider;
|
|||
import reborncore.client.containerBuilder.builder.BuiltContainer;
|
||||
import reborncore.client.containerBuilder.builder.ContainerBuilder;
|
||||
import techreborn.init.ModBlocks;
|
||||
import techreborn.init.ModSounds;
|
||||
import techreborn.lib.ModInfo;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by modmuss50 on 20/06/2017.
|
||||
|
@ -66,14 +66,17 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
@ConfigRegistry(config = "machines", category = "autocrafter", key = "AutoCrafterMaxEnergy", comment = "AutoCrafting Table Max Energy (Value in EU)")
|
||||
public static int maxEnergy = 10_000;
|
||||
|
||||
public int[] craftingSlots = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
private int outputSlot = 9;
|
||||
public Inventory inventory = new Inventory(11, "TileAutoCraftingTable", 64, this);
|
||||
public int progress;
|
||||
public IRecipe currentRecipe;
|
||||
public ItemStack currentRecipeOutput;
|
||||
public int tickTime;
|
||||
public int maxProgress = 120;
|
||||
public int euTick = 10;
|
||||
public int balanceSlot = 0;
|
||||
|
||||
InventoryCrafting inventoryCrafting = null;
|
||||
IRecipe lastCustomRecipe = null;
|
||||
IRecipe lastRecipe = null;
|
||||
|
||||
public boolean locked = true;
|
||||
|
||||
|
@ -81,25 +84,6 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
super();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IRecipe getIRecipe() {
|
||||
InventoryCrafting crafting = getCraftingInventory();
|
||||
if (!crafting.isEmpty()) {
|
||||
if (lastRecipe != null) {
|
||||
if (lastRecipe.matches(crafting, world)) {
|
||||
return lastRecipe;
|
||||
}
|
||||
}
|
||||
for (IRecipe testRecipe : CraftingManager.REGISTRY) {
|
||||
if (testRecipe.matches(crafting, world)) {
|
||||
lastRecipe = testRecipe;
|
||||
return testRecipe;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public InventoryCrafting getCraftingInventory() {
|
||||
if (inventoryCrafting == null) {
|
||||
inventoryCrafting = new InventoryCrafting(new Container() {
|
||||
|
@ -115,48 +99,24 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
return inventoryCrafting;
|
||||
}
|
||||
|
||||
public boolean canMake(IRecipe recipe) {
|
||||
if (recipe != null && recipe.canFit(3, 3)) {
|
||||
boolean missingOutput = false;
|
||||
int[] stacksInSlots = new int[9];
|
||||
for (int i = 0; i < 9; i++) {
|
||||
stacksInSlots[i] = inventory.getStackInSlot(i).getCount();
|
||||
}
|
||||
for (Ingredient ingredient : recipe.getIngredients()) {
|
||||
if (ingredient != Ingredient.EMPTY) {
|
||||
boolean foundIngredient = false;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack stack = inventory.getStackInSlot(i);
|
||||
int requiredSize = locked ? 1 : 0;
|
||||
if (stack.getMaxStackSize() == 1) {
|
||||
requiredSize = 0;
|
||||
}
|
||||
if (stacksInSlots[i] > requiredSize) {
|
||||
if (ingredient.apply(stack)) {
|
||||
if (stack.getItem().getContainerItem() != null) {
|
||||
if (!hasRoomForExtraItem(stack.getItem().getContainerItem(stack))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
foundIngredient = true;
|
||||
stacksInSlots[i]--;
|
||||
break;
|
||||
public boolean canMake(InventoryCrafting craftMatrix) {
|
||||
ItemStack stack = findMatchingRecipeOutput(craftMatrix);
|
||||
if (locked) {
|
||||
for (int i = 0; i < craftMatrix.getSizeInventory(); i++) {
|
||||
ItemStack stack1 = craftMatrix.getStackInSlot(i);
|
||||
if (!stack1.isEmpty() && stack1.getCount() < 2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundIngredient) {
|
||||
missingOutput = true;
|
||||
if (stack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!missingOutput) {
|
||||
if (hasOutputSpace(recipe.getRecipeOutput(), 9)) {
|
||||
ItemStack output = getStackInSlot(outputSlot);
|
||||
if (output.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
return ItemUtils.isItemEqual(stack, output, true, true);
|
||||
}
|
||||
|
||||
boolean hasRoomForExtraItem(ItemStack stack) {
|
||||
|
@ -180,41 +140,6 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean make(IRecipe recipe) {
|
||||
if (recipe == null || !canMake(recipe)) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < recipe.getIngredients().size(); i++) {
|
||||
Ingredient ingredient = recipe.getIngredients().get(i);
|
||||
// Looks for the best slot to take it from
|
||||
ItemStack bestSlot = inventory.getStackInSlot(i);
|
||||
if (ingredient.apply(bestSlot)) {
|
||||
handleContainerItem(bestSlot);
|
||||
bestSlot.shrink(1);
|
||||
} else {
|
||||
for (int j = 0; j < 9; j++) {
|
||||
ItemStack stack = inventory.getStackInSlot(j);
|
||||
if (ingredient.apply(stack)) {
|
||||
handleContainerItem(stack);
|
||||
stack.shrink(1); // TODO is this right? or do I need
|
||||
// to use it as an actull
|
||||
// crafting grid
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemStack output = inventory.getStackInSlot(9);
|
||||
// TODO fire forge recipe event
|
||||
ItemStack ouputStack = recipe.getCraftingResult(getCraftingInventory());
|
||||
if (output.isEmpty()) {
|
||||
inventory.setInventorySlotContents(9, ouputStack.copy());
|
||||
} else {
|
||||
// TODO use ouputStack in someway?
|
||||
output.grow(recipe.getRecipeOutput().getCount());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleContainerItem(ItemStack stack) {
|
||||
if (stack.getItem().hasContainerItem(stack)) {
|
||||
|
@ -241,61 +166,113 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isItemValidForRecipeSlot(IRecipe recipe, ItemStack stack, int slotID) {
|
||||
if (recipe == null) {
|
||||
return true;
|
||||
public Optional<InventoryCrafting> balanceRecipe(InventoryCrafting craftCache) {
|
||||
if (currentRecipe == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
int bestSlot = findBestSlotForStack(recipe, stack);
|
||||
if (bestSlot != -1) {
|
||||
return bestSlot == slotID;
|
||||
if (world.isRemote) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return true;
|
||||
if (!locked) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public int findBestSlotForStack(IRecipe recipe, ItemStack stack) {
|
||||
if (recipe == null) {
|
||||
return -1;
|
||||
if (craftCache.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
balanceSlot++;
|
||||
if (balanceSlot > craftCache.getSizeInventory()) {
|
||||
balanceSlot = 0;
|
||||
}
|
||||
//Find the best slot for each item in a recipe, and move it if needed
|
||||
ItemStack sourceStack = inventory.getStackInSlot(balanceSlot);
|
||||
if (sourceStack.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
List<Integer> possibleSlots = new ArrayList<>();
|
||||
for (int i = 0; i < recipe.getIngredients().size(); i++) {
|
||||
ItemStack stackInSlot = inventory.getStackInSlot(i);
|
||||
Ingredient ingredient = recipe.getIngredients().get(i);
|
||||
if (ingredient != Ingredient.EMPTY && ingredient.apply(stack)) {
|
||||
for (int s = 0; s < currentRecipe.getIngredients().size(); s++) {
|
||||
ItemStack stackInSlot = inventory.getStackInSlot(s);
|
||||
Ingredient ingredient = currentRecipe.getIngredients().get(s);
|
||||
if (ingredient != Ingredient.EMPTY && ingredient.apply(sourceStack)) {
|
||||
if (stackInSlot.isEmpty()) {
|
||||
possibleSlots.add(i);
|
||||
} else if (stackInSlot.getItem() == stack.getItem()
|
||||
&& stackInSlot.getItemDamage() == stack.getItemDamage()) {
|
||||
if (stackInSlot.getMaxStackSize() >= stackInSlot.getCount() + stack.getCount()) {
|
||||
possibleSlots.add(i);
|
||||
possibleSlots.add(s);
|
||||
} else if (stackInSlot.getItem() == sourceStack.getItem() && stackInSlot.getItemDamage() == sourceStack.getItemDamage()) {
|
||||
possibleSlots.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!possibleSlots.isEmpty()){
|
||||
int totalItems = possibleSlots.stream()
|
||||
.mapToInt(value -> inventory.getStackInSlot(value).getCount()).sum();
|
||||
int slots = possibleSlots.size();
|
||||
|
||||
//This makes an array of ints with the best possible slot distribution
|
||||
int[] split = new int[slots];
|
||||
int remainder = totalItems % slots;
|
||||
Arrays.fill(split, totalItems / slots);
|
||||
while (remainder > 0){
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
if(remainder > 0){
|
||||
split[i] +=1;
|
||||
remainder --;
|
||||
}
|
||||
// Slot, count
|
||||
Pair<Integer, Integer> smallestCount = null;
|
||||
}
|
||||
}
|
||||
|
||||
List<Integer> slotDistrubution = possibleSlots.stream()
|
||||
.mapToInt(value -> inventory.getStackInSlot(value).getCount())
|
||||
.boxed().collect(Collectors.toList());
|
||||
|
||||
boolean needsBalance = false;
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
int required = split[i];
|
||||
if(slotDistrubution.contains(required)){
|
||||
//We need to remove the int, not at the int, this seems to work around that
|
||||
slotDistrubution.remove(new Integer(required));
|
||||
} else {
|
||||
needsBalance = true;
|
||||
}
|
||||
}
|
||||
if (!needsBalance) {
|
||||
return Optional.empty();
|
||||
}
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
//Slot, count
|
||||
Pair<Integer, Integer> bestSlot = null;
|
||||
for (Integer slot : possibleSlots) {
|
||||
ItemStack slotStack = inventory.getStackInSlot(slot);
|
||||
if (slotStack.isEmpty()) {
|
||||
return slot;
|
||||
bestSlot = Pair.of(slot, 0);
|
||||
}
|
||||
if (smallestCount == null) {
|
||||
smallestCount = Pair.of(slot, slotStack.getCount());
|
||||
} else if (smallestCount.getRight() >= slotStack.getCount()) {
|
||||
smallestCount = Pair.of(slot, slotStack.getCount());
|
||||
if (bestSlot == null) {
|
||||
bestSlot = Pair.of(slot, slotStack.getCount());
|
||||
} else if (bestSlot.getRight() >= slotStack.getCount()) {
|
||||
bestSlot = Pair.of(slot, slotStack.getCount());
|
||||
}
|
||||
}
|
||||
if (smallestCount != null) {
|
||||
return smallestCount.getLeft();
|
||||
if (bestSlot == null
|
||||
|| bestSlot.getLeft() == balanceSlot
|
||||
|| bestSlot.getRight() == sourceStack.getCount()
|
||||
|| inventory.getStackInSlot(bestSlot.getLeft()).isEmpty()
|
||||
|| !ItemUtils.isItemEqual(sourceStack, inventory.getStackInSlot(bestSlot.getLeft()), true, true, true)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return -1;
|
||||
sourceStack.shrink(1);
|
||||
inventory.getStackInSlot(bestSlot.getLeft()).grow(1);
|
||||
inventory.hasChanged = true;
|
||||
|
||||
return Optional.of(getCraftingInventory());
|
||||
}
|
||||
|
||||
public int getProgress() {
|
||||
return progress;
|
||||
return tickTime;
|
||||
}
|
||||
|
||||
public void setProgress(int progress) {
|
||||
this.progress = progress;
|
||||
this.tickTime = progress;
|
||||
}
|
||||
|
||||
public int getMaxProgress() {
|
||||
|
@ -309,6 +286,19 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
this.maxProgress = maxProgress;
|
||||
}
|
||||
|
||||
public IRecipe findMatchingRecipe(InventoryCrafting crafting){
|
||||
for (IRecipe testRecipe : CraftingManager.REGISTRY) {
|
||||
if (testRecipe.matches(crafting, world)) {
|
||||
return testRecipe;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ItemStack findMatchingRecipeOutput(InventoryCrafting crafting){
|
||||
return findMatchingRecipe(crafting).getRecipeOutput();
|
||||
}
|
||||
|
||||
// TilePowerAcceptor
|
||||
@Override
|
||||
public void update() {
|
||||
|
@ -316,29 +306,64 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
if (world.isRemote) {
|
||||
return;
|
||||
}
|
||||
IRecipe recipe = getIRecipe();
|
||||
if (recipe != null) {
|
||||
if (progress >= maxProgress) {
|
||||
if (make(recipe)) {
|
||||
progress = 0;
|
||||
charge(10);
|
||||
|
||||
InventoryCrafting craftMatrix = getCraftingInventory();
|
||||
currentRecipe = findMatchingRecipe(craftMatrix);
|
||||
if (currentRecipe != null) {
|
||||
if (world.getTotalWorldTime() % 2 == 0) {
|
||||
Optional<InventoryCrafting> balanceResult = balanceRecipe(craftMatrix);
|
||||
if (balanceResult.isPresent()) {
|
||||
craftMatrix = balanceResult.get();
|
||||
}
|
||||
}
|
||||
currentRecipeOutput = currentRecipe.getCraftingResult(craftMatrix);
|
||||
} else {
|
||||
currentRecipeOutput = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (!currentRecipeOutput.isEmpty() && canMake(craftMatrix)) {
|
||||
if (tickTime >= Math.max((int) (maxProgress * (1.0 - getSpeedMultiplier())), 1)) {
|
||||
currentRecipeOutput = findMatchingRecipeOutput(craftMatrix);
|
||||
if (!currentRecipeOutput.isEmpty()) {
|
||||
boolean hasCrafted = false;
|
||||
if (inventory.getStackInSlot(outputSlot).isEmpty()) {
|
||||
inventory.setInventorySlotContents(outputSlot, currentRecipeOutput);
|
||||
tickTime = 0;
|
||||
hasCrafted = true;
|
||||
} else {
|
||||
if (inventory.getStackInSlot(outputSlot).getCount()
|
||||
+ currentRecipeOutput.getCount() <= currentRecipeOutput.getMaxStackSize()) {
|
||||
final ItemStack stack = inventory.getStackInSlot(outputSlot);
|
||||
stack.setCount(stack.getCount() + currentRecipeOutput.getCount());
|
||||
inventory.setInventorySlotContents(outputSlot, stack);
|
||||
tickTime = 0;
|
||||
hasCrafted = true;
|
||||
}
|
||||
}
|
||||
if (hasCrafted) {
|
||||
for (int i = 0; i < craftMatrix.getSizeInventory(); i++) {
|
||||
inventory.decrStackSize(i, 1);
|
||||
}
|
||||
currentRecipeOutput = ItemStack.EMPTY;
|
||||
currentRecipe = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (canMake(recipe)) {
|
||||
if (canUseEnergy(euTick)) {
|
||||
progress++;
|
||||
if (progress == 1) {
|
||||
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), ModSounds.AUTO_CRAFTING,
|
||||
SoundCategory.BLOCKS, 0.3F, 0.8F);
|
||||
tickTime = 0;
|
||||
}
|
||||
useEnergy(euTick);
|
||||
}
|
||||
} else {
|
||||
progress = 0;
|
||||
if (!currentRecipeOutput.isEmpty()) {
|
||||
if (canUseEnergy(getEuPerTick(euTick))
|
||||
&& tickTime < Math.max((int) (maxProgress * (1.0 - getSpeedMultiplier())), 1)
|
||||
&& canMake(craftMatrix)) {
|
||||
useEnergy(getEuPerTick(euTick));
|
||||
tickTime++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (recipe == null) {
|
||||
progress = 0;
|
||||
if (currentRecipeOutput.isEmpty()) {
|
||||
tickTime = 0;
|
||||
currentRecipe = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,42 +418,9 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
// TileLegacyMachineBase
|
||||
@Override
|
||||
public boolean canBeUpgraded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValidForSlot(int index, ItemStack stack) {
|
||||
int bestSlot = findBestSlotForStack(getIRecipe(), stack);
|
||||
if (bestSlot != -1) {
|
||||
return index == bestSlot;
|
||||
}
|
||||
return super.isItemValidForSlot(index, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSlotsForFace(EnumFacing side) {
|
||||
return new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInsertItem(int index, ItemStack stack, EnumFacing direction) {
|
||||
if (index > 8) {
|
||||
return false;
|
||||
}
|
||||
int bestSlot = findBestSlotForStack(getIRecipe(), stack);
|
||||
if (bestSlot != -1) {
|
||||
return index == bestSlot;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction) {
|
||||
if (index > 8) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This machine doesnt have a facing
|
||||
@Override
|
||||
|
@ -454,6 +446,7 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
return new ContainerBuilder("autocraftingtable").player(player.inventory).inventory().hotbar().addInventory()
|
||||
.tile(this).slot(0, 28, 25).slot(1, 46, 25).slot(2, 64, 25).slot(3, 28, 43).slot(4, 46, 43)
|
||||
.slot(5, 64, 43).slot(6, 28, 61).slot(7, 46, 61).slot(8, 64, 61).outputSlot(9, 145, 42)
|
||||
.onCraft(inv -> this.inventory.setInventorySlotContents(1, findMatchingRecipeOutput(getCraftingInventory())))
|
||||
.outputSlot(10, 145, 70).syncEnergyValue().syncIntegerValue(this::getProgress, this::setProgress)
|
||||
.syncIntegerValue(this::getMaxProgress, this::setMaxProgress)
|
||||
.syncIntegerValue(this::getLockedInt, this::setLockedInt).addInventory().create(this);
|
||||
|
@ -461,6 +454,6 @@ public class TileAutoCraftingTable extends TilePowerAcceptor
|
|||
|
||||
@Override
|
||||
public boolean hasSlotConfig() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue