Partially recipe output zindex. Closes #2288

This commit is contained in:
drcrazy 2020-11-14 16:25:25 +03:00
parent 69506d82f4
commit 05a55a3294
2 changed files with 141 additions and 156 deletions

View file

@ -66,13 +66,14 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
implements IToolDrop, InventoryProvider, BuiltScreenHandlerProvider {
public RebornInventory<AutoCraftingTableBlockEntity> inventory = new RebornInventory<>(11, "AutoCraftingTableBlockEntity", 64, this);
private final int OUTPUT_SLOT = 9;
private final int EXTRA_OUTPUT_SLOT = 10;
public int progress;
public int maxProgress = 120;
public int euTick = 10;
public int balanceSlot = 0;
CraftingInventory inventoryCrafting = null;
CraftingRecipe lastCustomRecipe = null;
CraftingRecipe lastRecipe = null;
public boolean locked = true;
@ -83,23 +84,22 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
@Nullable
public CraftingRecipe getCurrentRecipe() {
if (world == null) return null;
CraftingInventory crafting = getCraftingInventory();
if (!crafting.isEmpty()) {
if (lastRecipe != null) {
if (lastRecipe.matches(crafting, world)) {
return lastRecipe;
}
}
Optional<CraftingRecipe> testRecipe = world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, crafting, world);
if (testRecipe.isPresent()) {
lastRecipe = testRecipe.get();
return lastRecipe;
}
if (crafting.isEmpty()) return null;
if (lastRecipe != null && lastRecipe.matches(crafting, world)) return lastRecipe;
Optional<CraftingRecipe> testRecipe = world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, crafting, world);
if (testRecipe.isPresent()) {
lastRecipe = testRecipe.get();
return lastRecipe;
}
return null;
}
public CraftingInventory getCraftingInventory() {
private CraftingInventory getCraftingInventory() {
if (inventoryCrafting == null) {
inventoryCrafting = new CraftingInventory(new ScreenHandler(null, -1) {
@Override
@ -114,59 +114,35 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return inventoryCrafting;
}
public boolean canMake(CraftingRecipe recipe) {
if (recipe != null) {
boolean missingOutput = false;
int[] stacksInSlots = new int[9];
for (int i = 0; i < 9; i++) {
stacksInSlots[i] = inventory.getStack(i).getCount();
}
// Check if we have recipe, inputs and space for outputs
private boolean canMake(CraftingRecipe recipe) {
if (world == null) return false;
if (recipe == null) return false;
DefaultedList<Ingredient> ingredients = recipe.getPreviewInputs();
List<Integer> checkedSlots = new ArrayList<>();
for (Ingredient ingredient : ingredients) {
if (ingredient != Ingredient.EMPTY && !(ingredient.test(ItemStack.EMPTY))) {
boolean foundIngredient = false;
for (int i = 0; i < 9; i++) {
if (checkedSlots.contains(i)) {
continue;
}
ItemStack stack = inventory.getStack(i);
int requiredSize = locked ? 1 : 0;
if (stack.getMaxCount() == 1) {
requiredSize = 0;
}
if (stacksInSlots[i] > requiredSize) {
if (ingredient.test(stack)) {
foundIngredient = true;
checkedSlots.add(i);
stacksInSlots[i]--;
break;
}
}
}
if (!foundIngredient) {
missingOutput = true;
}
}
}
if (!missingOutput) {
return hasOutputSpace(recipe.getOutput(), 9);
}
return false;
CraftingInventory crafting = getCraftingInventory();
if (crafting.isEmpty()) return false;
if (!recipe.matches(crafting, world)) return false;
if (!hasOutputSpace(recipe.getOutput(), OUTPUT_SLOT)) return false;
DefaultedList<ItemStack> remainingStacks = world.getRecipeManager().getRemainingStacks(RecipeType.CRAFTING, crafting, world);
for (ItemStack stack : remainingStacks){
if (!stack.isEmpty() && !hasRoomForExtraItem(stack)) return false;
}
return false;
return true;
}
boolean hasRoomForExtraItem(ItemStack stack) {
ItemStack extraOutputSlot = inventory.getStack(10);
private boolean hasRoomForExtraItem(ItemStack stack) {
ItemStack extraOutputSlot = inventory.getStack(EXTRA_OUTPUT_SLOT);
if (extraOutputSlot.isEmpty()) {
return true;
}
return hasOutputSpace(stack, 10);
return hasOutputSpace(stack, EXTRA_OUTPUT_SLOT);
}
public boolean hasOutputSpace(ItemStack output, int slot) {
private boolean hasOutputSpace(ItemStack output, int slot) {
ItemStack stack = inventory.getStack(slot);
if (stack.isEmpty()) {
return true;
@ -177,7 +153,7 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return false;
}
public boolean make(CraftingRecipe recipe) {
private boolean make(CraftingRecipe recipe) {
if (recipe == null || !canMake(recipe)) {
return false;
}
@ -188,10 +164,9 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
ItemStack bestSlot = inventory.getStack(i);
if (ingredient.test(bestSlot)) {
ItemStack remainderStack = getRemainderItem(bestSlot);
if (remainderStack.isEmpty()) {
bestSlot.decrement(1);
} else {
inventory.setStack(i, remainderStack);
bestSlot.decrement(1);
if (!remainderStack.isEmpty()) {
moveExtraOutput(remainderStack);
}
} else {
@ -199,26 +174,34 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
ItemStack stack = inventory.getStack(j);
if (ingredient.test(stack)) {
ItemStack remainderStack = getRemainderItem(stack);
if (remainderStack.isEmpty()) {
stack.decrement(1);
} else {
inventory.setStack(j, remainderStack);
stack.decrement(1);
if (!remainderStack.isEmpty()) {
moveExtraOutput(remainderStack);
}
break;
}
}
}
}
ItemStack output = inventory.getStack(9);
ItemStack output = inventory.getStack(OUTPUT_SLOT);
ItemStack outputStack = recipe.craft(getCraftingInventory());
if (output.isEmpty()) {
inventory.setStack(9, outputStack.copy());
inventory.setStack(OUTPUT_SLOT, outputStack.copy());
} else {
output.increment(recipe.getOutput().getCount());
}
return true;
}
private void moveExtraOutput(ItemStack stack){
ItemStack currentExtraOutput = inventory.getStack(EXTRA_OUTPUT_SLOT);
if (currentExtraOutput.isEmpty()){
inventory.setStack(EXTRA_OUTPUT_SLOT, stack.copy());
} else {
currentExtraOutput.increment(stack.getCount());
}
}
private ItemStack getRemainderItem(ItemStack stack) {
if (stack.getItem() instanceof ExtendedRecipeRemainder) {
return ((ExtendedRecipeRemainder) stack.getItem()).getRemainderStack(stack);
@ -229,72 +212,15 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return ItemStack.EMPTY;
}
public int getProgress() {
return progress;
}
private Optional<CraftingInventory> balanceRecipe(CraftingInventory craftCache) {
if (world == null || world.isClient) return Optional.empty();
if (craftCache.isEmpty()) return Optional.empty();
public void setProgress(int progress) {
this.progress = progress;
}
public int getMaxProgress() {
if (maxProgress == 0) {
maxProgress = 1;
}
return maxProgress;
}
public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress;
}
// TilePowerAcceptor
@Override
public void tick() {
super.tick();
if (world.isClient) {
return;
}
CraftingRecipe recipe = getCurrentRecipe();
if (recipe != null) {
Optional<CraftingInventory> balanceResult = balanceRecipe(getCraftingInventory());
balanceResult.ifPresent(craftingInventory -> inventoryCrafting = craftingInventory);
if (progress >= maxProgress) {
if (make(recipe)) {
progress = 0;
}
} else {
if (canMake(recipe)) {
if (getStored(EnergySide.UNKNOWN) > euTick) {
progress++;
if (progress == 1) {
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), ModSounds.AUTO_CRAFTING,
SoundCategory.BLOCKS, 0.3F, 0.8F);
}
useEnergy(euTick);
}
} else {
progress = 0;
}
}
}
if (recipe == null) {
progress = 0;
}
}
public Optional<CraftingInventory> balanceRecipe(CraftingInventory craftCache) {
CraftingRecipe currentRecipe = getCurrentRecipe();
if (currentRecipe == null) {
return Optional.empty();
}
if (world.isClient) {
return Optional.empty();
}
if (craftCache.isEmpty()) {
return Optional.empty();
}
balanceSlot++;
if (balanceSlot > craftCache.size()) {
balanceSlot = 0;
@ -327,7 +253,7 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
.mapToInt(value -> inventory.getStack(value).getCount()).sum();
int slots = possibleSlots.size();
//This makes an array of ints with the best possible slot EnvTyperibution
//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);
@ -340,15 +266,15 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
}
}
List<Integer> slotEnvTyperubution = possibleSlots.stream()
List<Integer> slotDistribution = possibleSlots.stream()
.mapToInt(value -> inventory.getStack(value).getCount())
.boxed().collect(Collectors.toList());
boolean needsBalance = false;
for (int required : split) {
if (slotEnvTyperubution.contains(required)) {
if (slotDistribution.contains(required)) {
//We need to remove the int, not at the int, this seems to work around that
slotEnvTyperubution.remove(Integer.valueOf(required));
slotDistribution.remove(Integer.valueOf(required));
} else {
needsBalance = true;
}
@ -373,8 +299,7 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
bestSlot = Pair.of(slot, slotStack.getCount());
}
}
if (bestSlot == null
|| bestSlot.getLeft() == balanceSlot
if (bestSlot.getLeft() == balanceSlot
|| bestSlot.getRight() == sourceStack.getCount()
|| inventory.getStack(bestSlot.getLeft()).isEmpty()
|| !ItemUtils.isItemEqual(sourceStack, inventory.getStack(bestSlot.getLeft()), true, true)) {
@ -387,13 +312,40 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return Optional.of(getCraftingInventory());
}
// Easyest way to sync back to the client
public int getLockedInt() {
return locked ? 1 : 0;
}
// TilePowerAcceptor
@Override
public void tick() {
super.tick();
if (world == null || world.isClient) {
return;
}
CraftingRecipe recipe = getCurrentRecipe();
if (recipe == null) {
progress = 0;
return;
}
public void setLockedInt(int lockedInt) {
locked = lockedInt == 1;
Optional<CraftingInventory> balanceResult = balanceRecipe(getCraftingInventory());
balanceResult.ifPresent(craftingInventory -> inventoryCrafting = craftingInventory);
if (progress >= maxProgress) {
if (make(recipe)) {
progress = 0;
}
} else {
if (canMake(recipe)) {
if (getStored(EnergySide.UNKNOWN) > euTick) {
progress++;
if (progress == 1) {
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), ModSounds.AUTO_CRAFTING,
SoundCategory.BLOCKS, 0.3F, 0.8F);
}
useEnergy(euTick);
}
} else {
progress = 0;
}
}
}
@Override
@ -430,12 +382,17 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
super.fromTag(blockState, tag);
}
// TileMachineBase
// MachineBaseBlockEntity
@Override
public boolean canBeUpgraded() {
return false;
}
@Override
public boolean hasSlotConfig() {
return true;
}
// This machine doesnt have a facing
@Override
public Direction getFacingEnum() {
@ -448,25 +405,52 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return TRContent.Machine.AUTO_CRAFTING_TABLE.getStack();
}
// ItemHandlerProvider
// InventoryProvider
@Override
public RebornInventory<AutoCraftingTableBlockEntity> getInventory() {
return inventory;
}
// IContainerProvider
// BuiltScreenHandlerProvider
@Override
public BuiltScreenHandler createScreenHandler(int syncID, PlayerEntity player) {
return new ScreenHandlerBuilder("autocraftingtable").player(player.inventory).inventory().hotbar().addInventory()
.blockEntity(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)
.outputSlot(10, 145, 70).syncEnergyValue().sync(this::getProgress, this::setProgress)
.blockEntity(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(OUTPUT_SLOT, 145, 42)
.outputSlot(EXTRA_OUTPUT_SLOT, 145, 70)
.syncEnergyValue().sync(this::getProgress, this::setProgress)
.sync(this::getMaxProgress, this::setMaxProgress)
.sync(this::getLockedInt, this::setLockedInt).addInventory().create(this, syncID);
}
@Override
public boolean hasSlotConfig() {
return true;
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
}
public int getMaxProgress() {
if (maxProgress == 0) {
maxProgress = 1;
}
return maxProgress;
}
public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress;
}
public int getLockedInt() {
return locked ? 1 : 0;
}
public void setLockedInt(int lockedInt) {
locked = lockedInt == 1;
}
}

View file

@ -29,7 +29,6 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.CraftingRecipe;
import net.minecraft.text.LiteralText;
import net.minecraft.util.Identifier;
import reborncore.client.gui.builder.GuiBase;
import reborncore.client.gui.guibuilder.GuiBuilder;
@ -59,10 +58,6 @@ public class GuiAutoCrafting extends GuiBase<BuiltScreenHandler> {
@Override
protected void drawForeground(MatrixStack matrixStack, int mouseX, int mouseY) {
super.drawForeground(matrixStack, mouseX, mouseY);
CraftingRecipe recipe = blockEntityAutoCraftingTable.getCurrentRecipe();
if (recipe != null) {
renderItemStack(recipe.getOutput(), 95, 42);
}
final Layer layer = Layer.FOREGROUND;
builder.drawProgressBar(matrixStack, this, blockEntityAutoCraftingTable.getProgress(), blockEntityAutoCraftingTable.getMaxProgress(), 120, 44, mouseX, mouseY, GuiBuilder.ProgressDirection.RIGHT, layer);
@ -78,8 +73,14 @@ public class GuiAutoCrafting extends GuiBase<BuiltScreenHandler> {
drawSlot(matrixStack, 28 + (i * 18), 25 + (j * 18), layer);
}
}
drawOutputSlot(matrixStack, 145, 42, layer);
drawOutputSlot(matrixStack, 95, 42, layer);
drawOutputSlot(matrixStack, 145, 42, layer);
drawOutputSlot(matrixStack, 145, 70, layer);
CraftingRecipe recipe = blockEntityAutoCraftingTable.getCurrentRecipe();
if (recipe != null) {
renderItemStack(recipe.getOutput(), 95 + getGuiLeft(), 42 + getGuiTop());
}
builder.drawLockButton(matrixStack, this, 145, 4, mouseX, mouseY, layer, blockEntityAutoCraftingTable.locked);
}