Fix progress bar for electric furnace

This commit is contained in:
drcrazy 2019-08-15 21:14:42 +03:00
parent 9035e4376a
commit 3e5965ad57
2 changed files with 165 additions and 93 deletions

View file

@ -24,10 +24,13 @@
package techreborn.blockentity.machine.tier1; package techreborn.blockentity.machine.tier1;
import net.minecraft.block.BlockState; import java.util.Optional;
import net.minecraft.block.Block;
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.RecipeType; import net.minecraft.recipe.RecipeType;
import net.minecraft.recipe.SmeltingRecipe;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import reborncore.api.IToolDrop; import reborncore.api.IToolDrop;
import reborncore.api.blockentity.InventoryProvider; import reborncore.api.blockentity.InventoryProvider;
@ -36,105 +39,163 @@ import reborncore.client.containerBuilder.builder.BuiltContainer;
import reborncore.client.containerBuilder.builder.ContainerBuilder; import reborncore.client.containerBuilder.builder.ContainerBuilder;
import reborncore.common.blocks.BlockMachineBase; import reborncore.common.blocks.BlockMachineBase;
import reborncore.common.powerSystem.PowerAcceptorBlockEntity; import reborncore.common.powerSystem.PowerAcceptorBlockEntity;
import reborncore.common.recipes.RecipeCrafter;
import reborncore.common.util.ItemUtils;
import reborncore.common.util.RebornInventory; import reborncore.common.util.RebornInventory;
import techreborn.config.TechRebornConfig; import techreborn.config.TechRebornConfig;
import techreborn.init.TRContent; import techreborn.init.TRContent;
import techreborn.utils.RecipeUtils;
import techreborn.init.TRBlockEntities; import techreborn.init.TRBlockEntities;
public class ElectricFurnaceBlockEntity extends PowerAcceptorBlockEntity public class ElectricFurnaceBlockEntity extends PowerAcceptorBlockEntity
implements IToolDrop, InventoryProvider, IContainerProvider { implements IToolDrop, InventoryProvider, IContainerProvider {
public RebornInventory<ElectricFurnaceBlockEntity> inventory = new RebornInventory<>(3, "ElectricFurnaceBlockEntity", 64, this); public RebornInventory<ElectricFurnaceBlockEntity> inventory = new RebornInventory<>(3, "ElectricFurnaceBlockEntity", 64, this);
public int progress; int inputSlot = 0;
public int fuelScale = 100; int outputSlot = 1;
public int cost = 4; int ticksSinceLastChange;
int input1 = 0; private SmeltingRecipe currentRecipe;
int output = 1; private int cookTime;
boolean wasBurning = false; private int cookTimeTotal;
// Energy cost per tick of cooking
final int EnergyPerTick = 4;
public ElectricFurnaceBlockEntity() { public ElectricFurnaceBlockEntity() {
super(TRBlockEntities.ELECTRIC_FURNACE ); super(TRBlockEntities.ELECTRIC_FURNACE );
} }
public int gaugeProgressScaled(int scale) { private void setInvDirty(boolean isDiry) {
return progress * scale / (int) (fuelScale * (1.0 - getSpeedMultiplier())); inventory.setChanged(isDiry);
} }
public void cookItems() { private boolean isInvDirty() {
if (canSmelt()) { return inventory.hasChanged();
final ItemStack itemstack = RecipeUtils.getMatchingRecipes(world, RecipeType.SMELTING, inventory.getInvStack(input1));
if (inventory.getInvStack(output).isEmpty()) {
inventory.setInvStack(output, itemstack.copy());
} else if (inventory.getInvStack(output).isItemEqualIgnoreDamage(itemstack)) {
inventory.getInvStack(output).increment(itemstack.getCount());
}
if (inventory.getInvStack(input1).getCount() > 1) {
inventory.shrinkSlot(input1, 1);
} else {
inventory.setInvStack(input1, ItemStack.EMPTY);
}
}
} }
public boolean canSmelt() { private void updateCurrentRecipe() {
if (inventory.getInvStack(input1).isEmpty()) { if (inventory.getInvStack(inputSlot).isEmpty()) {
resetCrafter();
return;
}
Optional<SmeltingRecipe> testRecipe = world.getRecipeManager().getFirstMatch(RecipeType.SMELTING, inventory, world);
if (!testRecipe.isPresent()) {
resetCrafter();
return;
}
if (!canAcceptOutput(testRecipe.get(), outputSlot)) {
resetCrafter();
}
currentRecipe = testRecipe.get();
cookTime = 0;
cookTimeTotal = Math.max((int) (currentRecipe.getCookTime() * (1.0 - getSpeedMultiplier())), 1);
updateState();
}
private boolean canAcceptOutput(SmeltingRecipe recipe, int slot) {
ItemStack recipeOutput = recipe.getOutput();
if (recipeOutput.isEmpty()) {
return false; return false;
} }
final ItemStack itemstack = RecipeUtils.getMatchingRecipes(world, RecipeType.SMELTING, inventory.getInvStack(input1)); if (inventory.getInvStack(slot).isEmpty()) {
if (itemstack.isEmpty()) {
return false;
}
if (inventory.getInvStack(output).isEmpty()) {
return true; return true;
} }
if (!inventory.getInvStack(output).isItemEqualIgnoreDamage(itemstack)) { if (ItemUtils.isItemEqual(inventory.getInvStack(slot), recipeOutput, true, true)) {
if (recipeOutput.getCount() + inventory.getInvStack(slot).getCount() <= recipeOutput.getMaxCount()) {
return true;
}
}
return false;
}
public boolean canCraftAgain() {
if (inventory.getInvStack(inputSlot).isEmpty()) {
return false; return false;
} }
final int result = inventory.getInvStack(output).getCount() + itemstack.getCount(); if (currentRecipe == null) {
return result <= this.inventory.getStackLimit() && result <= itemstack.getMaxCount(); return false;
}
public boolean isBurning() {
return getEnergy() > getEuPerTick(cost);
}
public ItemStack getResultFor(ItemStack stack) {
final ItemStack result = RecipeUtils.getMatchingRecipes(world, RecipeType.SMELTING, stack);
if (!result.isEmpty()) {
return result.copy();
} }
return ItemStack.EMPTY; if (!canAcceptOutput(currentRecipe, outputSlot)) {
} return false;
}
public void updateState() { if (getEnergy() < currentRecipe.getCookTime() * getEuPerTick(EnergyPerTick)) {
if (wasBurning != (progress > 0)) { return false;
// skips updating the block state for 1 tick, to prevent the machine from
// turning on/off rapidly causing fps drops
if (wasBurning && progress == 0 && canSmelt()) {
wasBurning = true;
return;
}
final BlockState BlockStateContainer = world.getBlockState(pos);
if (BlockStateContainer.getBlock() instanceof BlockMachineBase) {
final BlockMachineBase blockMachineBase = (BlockMachineBase) BlockStateContainer.getBlock();
if (BlockStateContainer.get(BlockMachineBase.ACTIVE) != progress > 0)
blockMachineBase.setActive(progress > 0, world, pos);
}
wasBurning = (progress > 0);
} }
return true;
} }
public int getBurnTime() { private void resetCrafter() {
return progress; currentRecipe = null;
cookTime = 0;
cookTimeTotal = 0;
} }
public void setBurnTime(final int burnTime) { private void updateState() {
this.progress = burnTime; Block furnaceBlock = getWorld().getBlockState(pos).getBlock();
if (furnaceBlock instanceof BlockMachineBase) {
BlockMachineBase blockMachineBase = (BlockMachineBase) furnaceBlock;
boolean isActive = isActive() || canCraftAgain();
blockMachineBase.setActive(isActive, world, pos);
}
world.updateListeners(pos, world.getBlockState(pos), world.getBlockState(pos), 3);
} }
private boolean hasAllInputs(SmeltingRecipe recipe) {
if (recipe == null) {
return false;
}
if (inventory.getInvStack(inputSlot).isEmpty()) {
return false;
}
Optional<SmeltingRecipe> testRecipe = world.getRecipeManager().getFirstMatch(RecipeType.SMELTING, inventory, world);
if (!testRecipe.isPresent()) {
return false;
}
return true;
}
private void craftRecipe(SmeltingRecipe recipe) {
if (recipe == null) {
return;
}
if (!canAcceptOutput(recipe, outputSlot)) {
return;
}
ItemStack outputStack = inventory.getInvStack(outputSlot);
if (outputStack.isEmpty()) {
inventory.setInvStack(outputSlot, recipe.getOutput().copy());
}
else {
// Just increment. We already checked stack match and stack size
outputStack.increment(1);
}
inventory.getInvStack(inputSlot).decrement(1);
}
public int getProgressScaled(int scale) {
if (cookTimeTotal != 0) {
return cookTime * scale / cookTimeTotal;
}
return 0;
}
public int getCookTime() {
return cookTime;
}
public void setCookTime(int cookTime) {
this.cookTime = cookTime;
}
public int getCookTimeTotal() {
return cookTimeTotal;
}
public void setCookTimeTotal(int cookTimeTotal) {
this.cookTimeTotal = cookTimeTotal;
}
// TilePowerAcceptor // TilePowerAcceptor
@Override @Override
public void tick() { public void tick() {
@ -142,31 +203,42 @@ public class ElectricFurnaceBlockEntity extends PowerAcceptorBlockEntity
charge(2); charge(2);
if (world.isClient) { if (world.isClient) {
setInvDirty(false);
return; return;
} }
final boolean burning = isBurning(); ticksSinceLastChange++;
boolean updateInventory = false; // Force a has chanced every second
if (isBurning() && canSmelt()) { if (ticksSinceLastChange == 20) {
updateState(); setInvDirty(true);
if (canUseEnergy(getEuPerTick(cost))) { ticksSinceLastChange = 0;
useEnergy(getEuPerTick(cost)); }
progress++;
if (progress >= Math.max((int) (fuelScale * (1.0 - getSpeedMultiplier())), 5)) { if (isInvDirty()) {
progress = 0; if (currentRecipe == null) {
cookItems(); updateCurrentRecipe();
updateInventory = true; }
if (currentRecipe != null && !hasAllInputs(currentRecipe)) {
resetCrafter();
updateState();
}
}
if (currentRecipe != null) {
if (cookTime >= cookTimeTotal && hasAllInputs(currentRecipe)) {
craftRecipe(currentRecipe);
updateCurrentRecipe();
} else if (cookTime < cookTimeTotal) {
if (canUseEnergy(getEuPerTick(EnergyPerTick))) {
useEnergy(getEuPerTick(EnergyPerTick));
cookTime++;
if (cookTime == 1 || cookTime % 20 == 0 && RecipeCrafter.soundHanlder != null) {
RecipeCrafter.soundHanlder.playSound(false, this);
}
} }
} }
} else {
updateState();
}
if (burning != isBurning()) {
updateInventory = true;
}
if (updateInventory) {
markDirty();
} }
setInvDirty(false);
} }
@Override @Override
@ -211,6 +283,6 @@ public class ElectricFurnaceBlockEntity extends PowerAcceptorBlockEntity
public BuiltContainer createContainer(int syncID, final PlayerEntity player) { public BuiltContainer createContainer(int syncID, final PlayerEntity player) {
return new ContainerBuilder("electricfurnace").player(player.inventory).inventory().hotbar().addInventory() return new ContainerBuilder("electricfurnace").player(player.inventory).inventory().hotbar().addInventory()
.blockEntity(this).slot(0, 55, 45).outputSlot(1, 101, 45).energySlot(2, 8, 72).syncEnergyValue() .blockEntity(this).slot(0, 55, 45).outputSlot(1, 101, 45).energySlot(2, 8, 72).syncEnergyValue()
.syncIntegerValue(this::getBurnTime, this::setBurnTime).addInventory().create(this, syncID); .syncIntegerValue(this::getCookTime, this::setCookTime).syncIntegerValue(this::getCookTimeTotal, this::setCookTimeTotal).addInventory().create(this, syncID);
} }
} }

View file

@ -57,7 +57,7 @@ public class GuiElectricFurnace extends GuiBase<BuiltContainer> {
super.drawForeground(mouseX, mouseY); super.drawForeground(mouseX, mouseY);
Layer layer = Layer.FOREGROUND; Layer layer = Layer.FOREGROUND;
builder.drawProgressBar(this, blockEntity.gaugeProgressScaled(100), 100, 76, 48, mouseX, mouseY, GuiBuilder.ProgressDirection.RIGHT, layer); builder.drawProgressBar(this, blockEntity.getProgressScaled(100), 100, 76, 48, mouseX, mouseY, GuiBuilder.ProgressDirection.RIGHT, layer);
builder.drawMultiEnergyBar(this, 9, 19, (int) blockEntity.getEnergy(), (int) blockEntity.getMaxPower(), mouseX, mouseY, 0, layer); builder.drawMultiEnergyBar(this, 9, 19, (int) blockEntity.getEnergy(), (int) blockEntity.getMaxPower(), mouseX, mouseY, 0, layer);
} }
} }