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.block.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.CraftingInventory; import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.Ingredient;
@ -62,7 +63,7 @@ import java.util.stream.Collectors;
// TODO add tick and power bars. // TODO add tick and power bars.
public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
implements IToolDrop, InventoryProvider, BuiltScreenHandlerProvider { implements IToolDrop, InventoryProvider, BuiltScreenHandlerProvider {
public int[] craftingSlots = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8}; public int[] craftingSlots = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8};
private CraftingInventory craftCache; private CraftingInventory craftCache;
@ -77,7 +78,8 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
private final int outputSlot; private final int outputSlot;
public boolean locked = false; public boolean locked = false;
public int balanceSlot = 0; public int balanceSlot = 0;
RollingMachineRecipe lastRecipe = null;
private List<Item> cachedInventoryStructure = null;
public RollingMachineBlockEntity(BlockPos pos, BlockState state) { public RollingMachineBlockEntity(BlockPos pos, BlockState state) {
super(TRBlockEntities.ROLLING_MACHINE, pos, state); super(TRBlockEntities.ROLLING_MACHINE, pos, state);
outputSlot = 9; outputSlot = 9;
@ -111,68 +113,54 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
} }
charge(10); charge(10);
CraftingInventory craftMatrix = getCraftingMatrix(); CraftingInventory craftMatrix = getCraftingMatrix(true);
currentRecipe = findMatchingRecipe(craftMatrix, world); currentRecipe = findMatchingRecipe(craftMatrix, world);
if (currentRecipe != null) { if (currentRecipe != null) {
setIsActive(true);
if (world.getTime() % 2 == 0) { if (world.getTime() % 2 == 0) {
Optional<CraftingInventory> balanceResult = balanceRecipe(craftMatrix); balanceRecipe(craftMatrix);
if (balanceResult.isPresent()) {
craftMatrix = balanceResult.get();
}
} }
currentRecipeOutput = currentRecipe.craft(craftMatrix, getWorld().getRegistryManager()); currentRecipeOutput = currentRecipe.craft(craftMatrix, getWorld().getRegistryManager());
} else { } else {
currentRecipeOutput = ItemStack.EMPTY; currentRecipeOutput = ItemStack.EMPTY;
} }
craftMatrix = getCraftingMatrix();
if (!currentRecipeOutput.isEmpty() && canMake(craftMatrix)) { if (currentRecipeOutput.isEmpty() || !checkNotEmpty(craftMatrix)){
if (tickTime >= Math.max((int) (currentRecipe.getTime() * (1.0 - getSpeedMultiplier())), 1)) { // can't make anyway, reject.
currentRecipeOutput = findMatchingRecipeOutput(craftMatrix, world); tickTime = 0;
if (!currentRecipeOutput.isEmpty()) { setIsActive(false);
boolean hasCrafted = false; return;
if (inventory.getStack(outputSlot).isEmpty()) { }
inventory.setStack(outputSlot, currentRecipeOutput.copy()); // Now we ensured we can make something. Check energy state.
tickTime = 0; if (getStored() > getEuPerTick(currentRecipe.getPower())
hasCrafted = true; && tickTime < Math.max((int) (currentRecipe.getTime() * (1.0 - getSpeedMultiplier())), 1)
} else { && canMake(craftMatrix)) {
if (inventory.getStack(outputSlot).getCount() setIsActive(true);
+ currentRecipeOutput.getCount() <= currentRecipeOutput.getMaxCount()) { useEnergy(getEuPerTick(currentRecipe.getPower()));
final ItemStack stack = inventory.getStack(outputSlot); tickTime++;
stack.setCount(stack.getCount() + currentRecipeOutput.getCount());
inventory.setStack(outputSlot, stack);
tickTime = 0;
hasCrafted = true;
} else {
setIsActive(false);
}
}
if (hasCrafted) {
for (int i = 0; i < craftMatrix.size(); i++) {
inventory.shrinkSlot(i, 1);
}
currentRecipeOutput = ItemStack.EMPTY;
currentRecipe = null;
}
}
}
} else { } else {
tickTime = 0; setIsActive(false);
return;
} }
if (!currentRecipeOutput.isEmpty()) { // Cached recipe or valid recipe exists.
if (getStored() > getEuPerTick(currentRecipe.getPower()) // checked if we can make at least one.
&& tickTime < Math.max((int) (currentRecipe.getTime() * (1.0 - getSpeedMultiplier())), 1) if (tickTime >= Math.max((int) (currentRecipe.getTime() * (1.0 - getSpeedMultiplier())), 1)) {
&& canMake(craftMatrix)) { //craft one
useEnergy(getEuPerTick(currentRecipe.getPower())); if (inventory.getStack(outputSlot).isEmpty()) {
tickTime++; inventory.setStack(outputSlot, currentRecipeOutput.copy());
} else { }
setIsActive(false); else {
// we checked stack can fit in output slot in canMake()
inventory.getStack(outputSlot).increment(currentRecipeOutput.getCount());
} }
}
if (currentRecipeOutput.isEmpty()) {
tickTime = 0; tickTime = 0;
currentRecipe = null; for (int i = 0; i < craftMatrix.size(); i++) {
setIsActive(canMake(getCraftingMatrix())); inventory.shrinkSlot(i, 1);
}
if (!locked) {
currentRecipeOutput = ItemStack.EMPTY;
currentRecipe = null;
}
} }
} }
@ -224,7 +212,7 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
if (!possibleSlots.isEmpty()) { if (!possibleSlots.isEmpty()) {
int totalItems = possibleSlots.stream() int totalItems = possibleSlots.stream()
.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 distribution // This makes an array of ints with the best possible slot distribution
@ -241,8 +229,8 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
} }
List<Integer> slotEnvTyperubution = possibleSlots.stream() List<Integer> slotEnvTyperubution = 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) {
@ -274,10 +262,10 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
} }
} }
if (bestSlot == null if (bestSlot == null
|| 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)) {
return Optional.empty(); return Optional.empty();
} }
sourceStack.decrement(1); sourceStack.decrement(1);
@ -288,10 +276,14 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
} }
private CraftingInventory getCraftingMatrix() { private CraftingInventory getCraftingMatrix() {
return getCraftingMatrix(false);
}
private CraftingInventory getCraftingMatrix(boolean forceRefresh) {
if (craftCache == null) { if (craftCache == null) {
craftCache = new CraftingInventory(new RollingBEContainer(), 3, 3); craftCache = new CraftingInventory(new RollingBEContainer(), 3, 3);
} }
if (inventory.hasChanged()) { if (forceRefresh || inventory.hasChanged()) {
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
craftCache.setStack(i, inventory.getStack(i).copy()); craftCache.setStack(i, inventory.getStack(i).copy());
} }
@ -299,17 +291,44 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
} }
return craftCache; 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;
}
public boolean canMake(CraftingInventory craftMatrix) { private boolean checkNotEmpty(CraftingInventory craftMatrix) {
ItemStack stack = findMatchingRecipeOutput(craftMatrix, this.world); //checks if inventory is empty or considered quasi-empty.
if (locked) { 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++) { for (int i = 0; i < craftMatrix.size(); i++) {
ItemStack stack1 = craftMatrix.getStack(i); ItemStack stack1 = craftMatrix.getStack(i);
if (!stack1.isEmpty() && stack1.getCount() < 2) { if (stack1.getCount() == 1) {
return false; 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 (stack.isEmpty()) { if (stack.isEmpty()) {
return false; return false;
} }
@ -317,7 +336,7 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
if (output.isEmpty()) { if (output.isEmpty()) {
return true; 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) { public List<RollingMachineRecipe> getAllRecipe(World world) {
@ -333,14 +352,36 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
} }
public RollingMachineRecipe findMatchingRecipe(CraftingInventory inv, World world) { public RollingMachineRecipe findMatchingRecipe(CraftingInventory inv, World world) {
if (isCorrectCachedInventory()){
return lastRecipe;
}
cachedInventoryStructure = fastIntlayout();
for (RollingMachineRecipe recipe : getAllRecipe(world)) { for (RollingMachineRecipe recipe : getAllRecipe(world)) {
if (recipe.matches(inv, world)) { if (recipe.matches(inv, world)) {
lastRecipe = recipe;
return recipe; return recipe;
} }
} }
lastRecipe = null;
return 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 @Override
public ItemStack getToolDrop(final PlayerEntity entityPlayer) { public ItemStack getToolDrop(final PlayerEntity entityPlayer) {
return TRContent.Machine.ROLLING_MACHINE.getStack(); return TRContent.Machine.ROLLING_MACHINE.getStack();
@ -385,16 +426,16 @@ public class RollingMachineBlockEntity extends PowerAcceptorBlockEntity
@Override @Override
public BuiltScreenHandler createScreenHandler(int syncID, final PlayerEntity player) { public BuiltScreenHandler createScreenHandler(int syncID, final PlayerEntity player) {
return new ScreenHandlerBuilder("rollingmachine").player(player.getInventory()) return new ScreenHandlerBuilder("rollingmachine").player(player.getInventory())
.inventory().hotbar() .inventory().hotbar()
.addInventory().blockEntity(this) .addInventory().blockEntity(this)
.slot(0, 30, 22).slot(1, 48, 22).slot(2, 66, 22) .slot(0, 30, 22).slot(1, 48, 22).slot(2, 66, 22)
.slot(3, 30, 40).slot(4, 48, 40).slot(5, 66, 40) .slot(3, 30, 40).slot(4, 48, 40).slot(5, 66, 40)
.slot(6, 30, 58).slot(7, 48, 58).slot(8, 66, 58) .slot(6, 30, 58).slot(7, 48, 58).slot(8, 66, 58)
.onCraft(inv -> this.inventory.setStack(1, findMatchingRecipeOutput(getCraftingMatrix(), this.world))) .onCraft(inv -> this.inventory.setStack(1, findMatchingRecipeOutput(getCraftingMatrix(), this.world)))
.outputSlot(9, 124, 40) .outputSlot(9, 124, 40)
.energySlot(10, 8, 70) .energySlot(10, 8, 70)
.syncEnergyValue().sync(this::getBurnTime, this::setBurnTime).sync(this::getLockedInt, this::setLockedInt) .syncEnergyValue().sync(this::getBurnTime, this::setBurnTime).sync(this::getLockedInt, this::setLockedInt)
.sync(this::getCurrentRecipeTime, this::setCurrentRecipeTime).addInventory().create(this, syncID); .sync(this::getCurrentRecipeTime, this::setCurrentRecipeTime).addInventory().create(this, syncID);
} }
public int getCurrentRecipeTime() { public int getCurrentRecipeTime() {