optimize RollingMachineBlockEntity (#3124)

This commit is contained in:
AngelBottomless 2023-03-18 21:21:39 +09:00 committed by GitHub
parent f3a6e7a21f
commit 0b3eb68038
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -27,6 +27,7 @@ package techreborn.blockentity.machine.tier1;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.recipe.Ingredient;
@ -77,7 +78,8 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
private final int outputSlot;
public boolean locked = false;
public int balanceSlot = 0;
RollingMachineRecipe lastRecipe = null;
private List<Item> cachedInventoryStructure = null;
public RollingMachineBlockEntity(BlockPos pos, BlockState state) {
super(TRBlockEntities.ROLLING_MACHINE, pos, state);
outputSlot = 9;
@ -111,68 +113,54 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
}
charge(10);
CraftingInventory craftMatrix = getCraftingMatrix();
CraftingInventory craftMatrix = getCraftingMatrix(true);
currentRecipe = findMatchingRecipe(craftMatrix, world);
if (currentRecipe != null) {
setIsActive(true);
if (world.getTime() % 2 == 0) {
Optional<CraftingInventory> balanceResult = balanceRecipe(craftMatrix);
if (balanceResult.isPresent()) {
craftMatrix = balanceResult.get();
}
balanceRecipe(craftMatrix);
}
currentRecipeOutput = currentRecipe.craft(craftMatrix, getWorld().getRegistryManager());
} else {
currentRecipeOutput = ItemStack.EMPTY;
}
craftMatrix = getCraftingMatrix();
if (!currentRecipeOutput.isEmpty() && canMake(craftMatrix)) {
if (tickTime >= Math.max((int) (currentRecipe.getTime() * (1.0 - getSpeedMultiplier())), 1)) {
currentRecipeOutput = findMatchingRecipeOutput(craftMatrix, world);
if (!currentRecipeOutput.isEmpty()) {
boolean hasCrafted = false;
if (inventory.getStack(outputSlot).isEmpty()) {
inventory.setStack(outputSlot, currentRecipeOutput.copy());
if (currentRecipeOutput.isEmpty() || !checkNotEmpty(craftMatrix)){
// can't make anyway, reject.
tickTime = 0;
hasCrafted = true;
} else {
if (inventory.getStack(outputSlot).getCount()
+ currentRecipeOutput.getCount() <= currentRecipeOutput.getMaxCount()) {
final ItemStack stack = inventory.getStack(outputSlot);
stack.setCount(stack.getCount() + currentRecipeOutput.getCount());
inventory.setStack(outputSlot, stack);
tickTime = 0;
hasCrafted = true;
} else {
setIsActive(false);
return;
}
}
if (hasCrafted) {
for (int i = 0; i < craftMatrix.size(); i++) {
inventory.shrinkSlot(i, 1);
}
currentRecipeOutput = ItemStack.EMPTY;
currentRecipe = null;
}
}
}
} else {
tickTime = 0;
}
if (!currentRecipeOutput.isEmpty()) {
// Now we ensured we can make something. Check energy state.
if (getStored() > getEuPerTick(currentRecipe.getPower())
&& tickTime < Math.max((int) (currentRecipe.getTime() * (1.0 - getSpeedMultiplier())), 1)
&& canMake(craftMatrix)) {
setIsActive(true);
useEnergy(getEuPerTick(currentRecipe.getPower()));
tickTime++;
} else {
setIsActive(false);
return;
}
// Cached recipe or valid recipe exists.
// checked if we can make at least one.
if (tickTime >= Math.max((int) (currentRecipe.getTime() * (1.0 - getSpeedMultiplier())), 1)) {
//craft one
if (inventory.getStack(outputSlot).isEmpty()) {
inventory.setStack(outputSlot, currentRecipeOutput.copy());
}
else {
// we checked stack can fit in output slot in canMake()
inventory.getStack(outputSlot).increment(currentRecipeOutput.getCount());
}
if (currentRecipeOutput.isEmpty()) {
tickTime = 0;
for (int i = 0; i < craftMatrix.size(); i++) {
inventory.shrinkSlot(i, 1);
}
if (!locked) {
currentRecipeOutput = ItemStack.EMPTY;
currentRecipe = null;
setIsActive(canMake(getCraftingMatrix()));
}
}
}
@ -288,10 +276,14 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
}
private CraftingInventory getCraftingMatrix() {
return getCraftingMatrix(false);
}
private CraftingInventory getCraftingMatrix(boolean forceRefresh) {
if (craftCache == null) {
craftCache = new CraftingInventory(new RollingBEContainer(), 3, 3);
}
if (inventory.hasChanged()) {
if (forceRefresh || inventory.hasChanged()) {
for (int i = 0; i < 9; i++) {
craftCache.setStack(i, inventory.getStack(i).copy());
}
@ -299,17 +291,44 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
}
return craftCache;
}
private List<Item> fastIntlayout(){
if (this.inventory == null) return null;
ArrayList<Item> arrayList = new ArrayList<>(9);
for (int i = 0; i < 9; i++){
arrayList.add(this.inventory.getStack(i).getItem());
}
return arrayList;
}
private boolean checkNotEmpty(CraftingInventory craftMatrix) {
//checks if inventory is empty or considered quasi-empty.
if (locked) {
boolean returnValue = false;
// for locked condition, we need to check if inventory contains item and all slots are empty or has more than one item.
for (int i = 0; i < craftMatrix.size(); i++) {
ItemStack stack1 = craftMatrix.getStack(i);
if (stack1.getCount() == 1) {
return false;
}
if (stack1.getCount() > 1) {
returnValue = true;
}
}
return returnValue;
}
else {
for (int i = 0; i < craftMatrix.size(); i++) {
ItemStack stack1 = craftMatrix.getStack(i);
if (!stack1.isEmpty()) {
return true;
}
}
}
return false;
}
public boolean canMake(CraftingInventory craftMatrix) {
ItemStack stack = findMatchingRecipeOutput(craftMatrix, this.world);
if (locked) {
for (int i = 0; i < craftMatrix.size(); i++) {
ItemStack stack1 = craftMatrix.getStack(i);
if (!stack1.isEmpty() && stack1.getCount() < 2) {
return false;
}
}
}
if (stack.isEmpty()) {
return false;
}
@ -317,7 +336,7 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
if (output.isEmpty()) {
return true;
}
return ItemUtils.isItemEqual(stack, output, true, true);
return ItemUtils.isItemEqual(stack, output, true, true) && output.getCount() + stack.getCount() <= output.getMaxCount();
}
public List<RollingMachineRecipe> getAllRecipe(World world) {
@ -333,14 +352,36 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
}
public RollingMachineRecipe findMatchingRecipe(CraftingInventory inv, World world) {
if (isCorrectCachedInventory()){
return lastRecipe;
}
cachedInventoryStructure = fastIntlayout();
for (RollingMachineRecipe recipe : getAllRecipe(world)) {
if (recipe.matches(inv, world)) {
lastRecipe = recipe;
return recipe;
}
}
lastRecipe = null;
return null;
}
private boolean isCorrectCachedInventory(){
if (cachedInventoryStructure == null){
return false;
}
List<Item> current = fastIntlayout();
if (current == null || current.size() != this.cachedInventoryStructure.size()){
return false;
}
for (int i = 0; i < current.size(); i++ ){
if (current.get(i) != this.cachedInventoryStructure.get(i)){
return false;
}
}
return true;
}
@Override
public ItemStack getToolDrop(final PlayerEntity entityPlayer) {
return TRContent.Machine.ROLLING_MACHINE.getStack();