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 { implements IToolDrop, InventoryProvider, BuiltScreenHandlerProvider {
public RebornInventory<AutoCraftingTableBlockEntity> inventory = new RebornInventory<>(11, "AutoCraftingTableBlockEntity", 64, this); 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 progress;
public int maxProgress = 120; public int maxProgress = 120;
public int euTick = 10; public int euTick = 10;
public int balanceSlot = 0; public int balanceSlot = 0;
CraftingInventory inventoryCrafting = null; CraftingInventory inventoryCrafting = null;
CraftingRecipe lastCustomRecipe = null;
CraftingRecipe lastRecipe = null; CraftingRecipe lastRecipe = null;
public boolean locked = true; public boolean locked = true;
@ -83,23 +84,22 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
@Nullable @Nullable
public CraftingRecipe getCurrentRecipe() { public CraftingRecipe getCurrentRecipe() {
if (world == null) return null;
CraftingInventory crafting = getCraftingInventory(); CraftingInventory crafting = getCraftingInventory();
if (!crafting.isEmpty()) { if (crafting.isEmpty()) return null;
if (lastRecipe != null) {
if (lastRecipe.matches(crafting, world)) { if (lastRecipe != null && lastRecipe.matches(crafting, world)) return lastRecipe;
return lastRecipe;
}
}
Optional<CraftingRecipe> testRecipe = world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, crafting, world); Optional<CraftingRecipe> testRecipe = world.getRecipeManager().getFirstMatch(RecipeType.CRAFTING, crafting, world);
if (testRecipe.isPresent()) { if (testRecipe.isPresent()) {
lastRecipe = testRecipe.get(); lastRecipe = testRecipe.get();
return lastRecipe; return lastRecipe;
} }
}
return null; return null;
} }
public CraftingInventory getCraftingInventory() { private CraftingInventory getCraftingInventory() {
if (inventoryCrafting == null) { if (inventoryCrafting == null) {
inventoryCrafting = new CraftingInventory(new ScreenHandler(null, -1) { inventoryCrafting = new CraftingInventory(new ScreenHandler(null, -1) {
@Override @Override
@ -114,59 +114,35 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return inventoryCrafting; return inventoryCrafting;
} }
public boolean canMake(CraftingRecipe recipe) { // Check if we have recipe, inputs and space for outputs
if (recipe != null) { private boolean canMake(CraftingRecipe recipe) {
boolean missingOutput = false; if (world == null) return false;
int[] stacksInSlots = new int[9]; if (recipe == null) return false;
for (int i = 0; i < 9; i++) {
stacksInSlots[i] = inventory.getStack(i).getCount(); 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;
} }
DefaultedList<Ingredient> ingredients = recipe.getPreviewInputs(); return true;
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;
}
return false;
} }
boolean hasRoomForExtraItem(ItemStack stack) { private boolean hasRoomForExtraItem(ItemStack stack) {
ItemStack extraOutputSlot = inventory.getStack(10); ItemStack extraOutputSlot = inventory.getStack(EXTRA_OUTPUT_SLOT);
if (extraOutputSlot.isEmpty()) { if (extraOutputSlot.isEmpty()) {
return true; 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); ItemStack stack = inventory.getStack(slot);
if (stack.isEmpty()) { if (stack.isEmpty()) {
return true; return true;
@ -177,7 +153,7 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return false; return false;
} }
public boolean make(CraftingRecipe recipe) { private boolean make(CraftingRecipe recipe) {
if (recipe == null || !canMake(recipe)) { if (recipe == null || !canMake(recipe)) {
return false; return false;
} }
@ -188,10 +164,9 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
ItemStack bestSlot = inventory.getStack(i); ItemStack bestSlot = inventory.getStack(i);
if (ingredient.test(bestSlot)) { if (ingredient.test(bestSlot)) {
ItemStack remainderStack = getRemainderItem(bestSlot); ItemStack remainderStack = getRemainderItem(bestSlot);
if (remainderStack.isEmpty()) {
bestSlot.decrement(1); bestSlot.decrement(1);
} else { if (!remainderStack.isEmpty()) {
inventory.setStack(i, remainderStack); moveExtraOutput(remainderStack);
} }
} else { } else {
@ -199,26 +174,34 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
ItemStack stack = inventory.getStack(j); ItemStack stack = inventory.getStack(j);
if (ingredient.test(stack)) { if (ingredient.test(stack)) {
ItemStack remainderStack = getRemainderItem(stack); ItemStack remainderStack = getRemainderItem(stack);
if (remainderStack.isEmpty()) {
stack.decrement(1); stack.decrement(1);
} else { if (!remainderStack.isEmpty()) {
inventory.setStack(j, remainderStack); moveExtraOutput(remainderStack);
} }
break; break;
} }
} }
} }
} }
ItemStack output = inventory.getStack(9); ItemStack output = inventory.getStack(OUTPUT_SLOT);
ItemStack outputStack = recipe.craft(getCraftingInventory()); ItemStack outputStack = recipe.craft(getCraftingInventory());
if (output.isEmpty()) { if (output.isEmpty()) {
inventory.setStack(9, outputStack.copy()); inventory.setStack(OUTPUT_SLOT, outputStack.copy());
} else { } else {
output.increment(recipe.getOutput().getCount()); output.increment(recipe.getOutput().getCount());
} }
return true; 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) { private ItemStack getRemainderItem(ItemStack stack) {
if (stack.getItem() instanceof ExtendedRecipeRemainder) { if (stack.getItem() instanceof ExtendedRecipeRemainder) {
return ((ExtendedRecipeRemainder) stack.getItem()).getRemainderStack(stack); return ((ExtendedRecipeRemainder) stack.getItem()).getRemainderStack(stack);
@ -229,72 +212,15 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
public int getProgress() { private Optional<CraftingInventory> balanceRecipe(CraftingInventory craftCache) {
return progress; 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(); CraftingRecipe currentRecipe = getCurrentRecipe();
if (currentRecipe == null) { if (currentRecipe == null) {
return Optional.empty(); return Optional.empty();
} }
if (world.isClient) {
return Optional.empty();
}
if (craftCache.isEmpty()) {
return Optional.empty();
}
balanceSlot++; balanceSlot++;
if (balanceSlot > craftCache.size()) { if (balanceSlot > craftCache.size()) {
balanceSlot = 0; balanceSlot = 0;
@ -327,7 +253,7 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
.mapToInt(value -> inventory.getStack(value).getCount()).sum(); .mapToInt(value -> inventory.getStack(value).getCount()).sum();
int slots = possibleSlots.size(); 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[] split = new int[slots];
int remainder = totalItems % slots; int remainder = totalItems % slots;
Arrays.fill(split, 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()) .mapToInt(value -> inventory.getStack(value).getCount())
.boxed().collect(Collectors.toList()); .boxed().collect(Collectors.toList());
boolean needsBalance = false; boolean needsBalance = false;
for (int required : split) { 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 //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 { } else {
needsBalance = true; needsBalance = true;
} }
@ -373,8 +299,7 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
bestSlot = Pair.of(slot, slotStack.getCount()); bestSlot = Pair.of(slot, slotStack.getCount());
} }
} }
if (bestSlot == null if (bestSlot.getLeft() == balanceSlot
|| bestSlot.getLeft() == balanceSlot
|| bestSlot.getRight() == sourceStack.getCount() || bestSlot.getRight() == sourceStack.getCount()
|| inventory.getStack(bestSlot.getLeft()).isEmpty() || inventory.getStack(bestSlot.getLeft()).isEmpty()
|| !ItemUtils.isItemEqual(sourceStack, inventory.getStack(bestSlot.getLeft()), true, true)) { || !ItemUtils.isItemEqual(sourceStack, inventory.getStack(bestSlot.getLeft()), true, true)) {
@ -387,13 +312,40 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return Optional.of(getCraftingInventory()); return Optional.of(getCraftingInventory());
} }
// Easyest way to sync back to the client // TilePowerAcceptor
public int getLockedInt() { @Override
return locked ? 1 : 0; 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) { Optional<CraftingInventory> balanceResult = balanceRecipe(getCraftingInventory());
locked = lockedInt == 1; 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 @Override
@ -430,12 +382,17 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
super.fromTag(blockState, tag); super.fromTag(blockState, tag);
} }
// TileMachineBase // MachineBaseBlockEntity
@Override @Override
public boolean canBeUpgraded() { public boolean canBeUpgraded() {
return false; return false;
} }
@Override
public boolean hasSlotConfig() {
return true;
}
// This machine doesnt have a facing // This machine doesnt have a facing
@Override @Override
public Direction getFacingEnum() { public Direction getFacingEnum() {
@ -448,25 +405,52 @@ public class AutoCraftingTableBlockEntity extends PowerAcceptorBlockEntity
return TRContent.Machine.AUTO_CRAFTING_TABLE.getStack(); return TRContent.Machine.AUTO_CRAFTING_TABLE.getStack();
} }
// ItemHandlerProvider // InventoryProvider
@Override @Override
public RebornInventory<AutoCraftingTableBlockEntity> getInventory() { public RebornInventory<AutoCraftingTableBlockEntity> getInventory() {
return inventory; return inventory;
} }
// IContainerProvider // BuiltScreenHandlerProvider
@Override @Override
public BuiltScreenHandler createScreenHandler(int syncID, PlayerEntity player) { public BuiltScreenHandler createScreenHandler(int syncID, PlayerEntity player) {
return new ScreenHandlerBuilder("autocraftingtable").player(player.inventory).inventory().hotbar().addInventory() 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) .blockEntity(this)
.slot(5, 64, 43).slot(6, 28, 61).slot(7, 46, 61).slot(8, 64, 61).outputSlot(9, 145, 42) .slot(0, 28, 25).slot(1, 46, 25).slot(2, 64, 25)
.outputSlot(10, 145, 70).syncEnergyValue().sync(this::getProgress, this::setProgress) .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::getMaxProgress, this::setMaxProgress)
.sync(this::getLockedInt, this::setLockedInt).addInventory().create(this, syncID); .sync(this::getLockedInt, this::setLockedInt).addInventory().create(this, syncID);
} }
@Override public int getProgress() {
public boolean hasSlotConfig() { return progress;
return true;
} }
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.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.recipe.CraftingRecipe; import net.minecraft.recipe.CraftingRecipe;
import net.minecraft.text.LiteralText;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import reborncore.client.gui.builder.GuiBase; import reborncore.client.gui.builder.GuiBase;
import reborncore.client.gui.guibuilder.GuiBuilder; import reborncore.client.gui.guibuilder.GuiBuilder;
@ -59,10 +58,6 @@ public class GuiAutoCrafting extends GuiBase<BuiltScreenHandler> {
@Override @Override
protected void drawForeground(MatrixStack matrixStack, int mouseX, int mouseY) { protected void drawForeground(MatrixStack matrixStack, int mouseX, int mouseY) {
super.drawForeground(matrixStack, mouseX, mouseY); super.drawForeground(matrixStack, mouseX, mouseY);
CraftingRecipe recipe = blockEntityAutoCraftingTable.getCurrentRecipe();
if (recipe != null) {
renderItemStack(recipe.getOutput(), 95, 42);
}
final Layer layer = Layer.FOREGROUND; final Layer layer = Layer.FOREGROUND;
builder.drawProgressBar(matrixStack, this, blockEntityAutoCraftingTable.getProgress(), blockEntityAutoCraftingTable.getMaxProgress(), 120, 44, mouseX, mouseY, GuiBuilder.ProgressDirection.RIGHT, layer); 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); drawSlot(matrixStack, 28 + (i * 18), 25 + (j * 18), layer);
} }
} }
drawOutputSlot(matrixStack, 145, 42, layer);
drawOutputSlot(matrixStack, 95, 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); builder.drawLockButton(matrixStack, this, 145, 4, mouseX, mouseY, layer, blockEntityAutoCraftingTable.locked);
} }