diff options
author | David Vierra <codewarrior@hawaii.rr.com> | 2018-01-28 03:03:09 -1000 |
---|---|---|
committer | David Vierra <codewarrior@hawaii.rr.com> | 2018-01-28 03:07:05 -1000 |
commit | c691dafed53cd962993df166d8d50cab535bf459 (patch) | |
tree | 4f195951c9eb37e624c4e51dd802d04be257b6ff /src/Java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations | |
parent | f7594feadd1c947eccf7e3c611b0b3ec75cd16ea (diff) | |
download | GT5-Unofficial-c691dafed53cd962993df166d8d50cab535bf459.tar.gz GT5-Unofficial-c691dafed53cd962993df166d8d50cab535bf459.tar.bz2 GT5-Unofficial-c691dafed53cd962993df166d8d50cab535bf459.zip |
Rewrite and refactor checkRecipe() for several multiblocks, restore machine sounds
`checkRecipeGeneric()` implements parallel processing, EU/t discounts
and speed boosts, increased random chances, and can be used to consider
each input bus individually (as seen in the Industrial Material Press)
to allow each bus to use a different Configuration Circuit. Also
considers the voltage input limit of the multiblock when counting
recipes to do in parallel - if the energy hatch is too small, it will
process fewer recipes at once. Plays the machine's sound, if any, on
success.
`checkRecipeGeneric()` also checks `canBufferOutput()` and will pause
the machine if it has no bus/hatch room for the recipe output.
`getValidOutputSlots()` is rewritten as `canBufferOutput()`, which
now checks both the item output buses and fluid output hatches to make
sure recipe output can be accepted. This is used to pause a machine
instead of allowing it to continue working and void outputs, if the
outputs can't be stored in a bus and/or hatch. NOTE:
`canBufferOutput()` doesn't consider parallel processing, so there are
a few recipes where, if done in parallel, it may get a false positive on
the buffer check and void some outputs. In practice, this will rarely
happen.
Removed unused imports, fields, and locals.
Industrial Centrifuge now uses `checkRecipeGeneric()` with 4 parallel
recipes and a 40% speed boost.
Industrial Coke Oven now uses `checkRecipeGeneric()` with 12 parallel
recipes if using Heat-Resistant Casings, or 24 if using Heat-Proof
Casings. Sound plays while processing.
Industrial Cutting Machine now uses `checkRecipeGeneric()` with 2
parallel recipes and a 60% speed boost. Pollution removed since the
Machine is built with no Muffler Hatch.
Industrial Electrolyzer now uses `checkRecipeGeneric()` with 2 parallel
recipes and a 40% speed boost.
Maceration Stack now uses `checkRecipeGeneric()` with 8*tTier
parallel recipes, a 60% speed boost, and an increased amount (~33%) of
random outputs. Sound plays while processing.
Material Press now uses `checkRecipeGeneric()` with 2 parallel recipes
and a 50% speed boost. Each input bus is considered separately for
finding recipes, allowing each bus to hold a different Configuration
Circuit. Sound plays while processing.
Industrial Sifter now uses `checkRecipeGeneric()` with 2 parallel
recipes, a 400% speed boost, and an increased amount (~15%) of random
outputs. Changed particles to appear above the sieve grates.
Industrial Thermal Centrifuge now uses `checkRecipeGeneric()` with 2
parallel recipes and a 60% speed boost.
Industrial Washing Plant now uses `checkRecipeGeneric()` with 2
parallel recipes and an 80% speed boost. Stone Dust outputs are no
longer deleted.
Wire Factory now uses `checkRecipeGeneric()` with 2 parallel recipes
and a 60% speed boost. Sound plays while processing.
Diffstat (limited to 'src/Java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations')
-rw-r--r-- | src/Java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java | 224 |
1 files changed, 198 insertions, 26 deletions
diff --git a/src/Java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java b/src/Java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java index 4e353003f4..ec955410d2 100644 --- a/src/Java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java +++ b/src/Java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java @@ -3,8 +3,12 @@ package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base; import java.lang.reflect.*; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; -import org.apache.commons.lang3.reflect.FieldUtils; +import gregtech.api.GregTech_API; +import gregtech.api.util.GT_Utility; +import net.minecraftforge.fluids.FluidStack; +import org.apache.commons.lang3.ArrayUtils; import gregtech.api.enums.Materials; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; @@ -14,7 +18,6 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.implementations.*; import gregtech.api.util.GT_Recipe; import gtPlusPlus.api.objects.Logger; -import gtPlusPlus.core.lib.CORE; import gtPlusPlus.core.lib.LoadedMods; import gtPlusPlus.core.util.PollutionUtils; import gtPlusPlus.core.util.math.MathUtils; @@ -27,11 +30,14 @@ import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; +import static gtPlusPlus.core.util.array.ArrayUtils.removeNulls; + public abstract class GregtechMeta_MultiBlockBase extends GT_MetaTileEntity_MultiBlockBase { - public static boolean disableMaintenance; + public GT_Recipe mLastRecipe; + public ArrayList<GT_MetaTileEntity_Hatch_InputBattery> mChargeHatches = new ArrayList<GT_MetaTileEntity_Hatch_InputBattery>(); public ArrayList<GT_MetaTileEntity_Hatch_OutputBattery> mDischargeHatches = new ArrayList<GT_MetaTileEntity_Hatch_OutputBattery>(); @@ -97,45 +103,211 @@ GT_MetaTileEntity_MultiBlockBase { @Override public void startSoundLoop(final byte aIndex, final double aX, final double aY, final double aZ) { + super.startSoundLoop(aIndex, aX, aY, aZ); + if (aIndex == 1) { + GT_Utility.doSoundAtClient(getSound(), 10, 1.0F, aX, aY, aZ); + } } public void startProcess() { + if(GT_Utility.isStringValid(getSound())) this.sendLoopStart((byte) 1); } - public int getValidOutputSlots(final IGregTechTileEntity machineCalling, - final GT_Recipe sRecipes, final ItemStack[] sInputs) { - Logger.WARNING("Finding valid output slots for " - + machineCalling.getInventoryName()); - final ArrayList<ItemStack> tInputList = this.getStoredInputs(); - final GT_Recipe tRecipe = sRecipes; - final int outputItemCount = tRecipe.mOutputs.length; - int tValidOutputHatches = 0; + public String getSound() { return ""; } - for (final GT_MetaTileEntity_Hatch_OutputBus tHatch : this.mOutputBusses) { - if (!isValidMetaTileEntity(tHatch)) { + public boolean canBufferOutputs(final GT_Recipe aRecipe) { + // Count slots available in hatches + int tEmptySlots = 0; + for (final GT_MetaTileEntity_Hatch_OutputBus tBus : this.mOutputBusses) { + if (!isValidMetaTileEntity(tBus)) { continue; } + final IInventory tBusInv = tBus.getBaseMetaTileEntity(); + for (int i = 0; i < tBusInv.getSizeInventory(); i++) { + if (tBus.getStackInSlot(i) == null) { + tEmptySlots++; + } + } + } - int tEmptySlots = 0; - boolean foundRoom = false; - final IInventory tHatchInv = tHatch.getBaseMetaTileEntity(); - for (int i = 0; (i < tHatchInv.getSizeInventory()) - && !foundRoom; ++i) { - if (tHatchInv.getStackInSlot(i) != null) { - continue; + // TODO: Check if any of the output stacks can stack with the stacks in the hatches? + // Enough open slots? + if (tEmptySlots < aRecipe.mOutputs.length) return false; + + // For each output fluid, make sure an output hatch can accept it. + for (FluidStack tRecipeFluid: aRecipe.mFluidOutputs) { + boolean tCanBufferFluid = false; + int tRecipeAmount = tRecipeFluid.amount; + for (final GT_MetaTileEntity_Hatch_Output tHatch : this.mOutputHatches) { + FluidStack tHatchFluid = tHatch.getFluid(); + if (tHatchFluid == null) { + if(tHatch.getCapacity() > tRecipeAmount) { + tCanBufferFluid = true; + break; + } + } + else if (tHatchFluid.isFluidEqual(tRecipeFluid) && tHatch.getCapacity() - tHatchFluid.amount > tRecipeAmount) { + tCanBufferFluid = true; + break; } + } + if (!tCanBufferFluid) return false; + } + return true; + } + + public boolean checkRecipeGeneric() { + return checkRecipeGeneric(1, 100, 0); + } + + public boolean checkRecipeGeneric(int aMaxParallelRecipes, int aEUPercent, int aSpeedBonusPercent) { + return checkRecipeGeneric(aMaxParallelRecipes, aEUPercent, aSpeedBonusPercent, 10000); + } + + public boolean checkRecipeGeneric(int aMaxParallelRecipes, int aEUPercent, int aSpeedBonusPercent, int aOutputChanceRoll) { + ArrayList<ItemStack> tItems = getStoredInputs(); + ArrayList<FluidStack> tFluids = getStoredFluids(); + ItemStack[] tItemInputs = tItems.toArray(new ItemStack[tItems.size()]); + FluidStack[] tFluidInputs = tFluids.toArray(new FluidStack[tFluids.size()]); + return checkRecipeGeneric(tItemInputs, tFluidInputs, aMaxParallelRecipes, aEUPercent, aSpeedBonusPercent, aOutputChanceRoll); + } + + public boolean checkRecipeGeneric( + ItemStack[] aItemInputs, FluidStack[] aFluidInputs, + int aMaxParallelRecipes, int aEUPercent, + int aSpeedBonusPercent, int aOutputChanceRoll) { + + + // Based on the Processing Array. A bit overkill, but very flexible. + long tVoltage = getMaxInputVoltage(); + byte tTier = (byte) Math.max(1, GT_Utility.getTier(tVoltage)); + + int parallelRecipes = 0; + + GT_Recipe tRecipe = this.getRecipeMap().findRecipe( + getBaseMetaTileEntity(), mLastRecipe, false, + gregtech.api.enums.GT_Values.V[tTier], aFluidInputs, aItemInputs); + + // Remember last recipe - an optimization for findRecipe() + this.mLastRecipe = tRecipe; + + if (tRecipe == null) { + return false; + } + + if (!this.canBufferOutputs(tRecipe)) { + return false; + } + + // Convert speed bonus to duration multiplier + // e.g. 100% speed bonus = 200% speed = 100%/200% = 50% recipe duration. + aSpeedBonusPercent = Math.max(-99, aSpeedBonusPercent); + float tTimeFactor = 100.0f / (100.0f + aSpeedBonusPercent); + this.mMaxProgresstime = (int)(tRecipe.mDuration * tTimeFactor); + + // EU discount + float tRecipeEUt = (tRecipe.mEUt * aEUPercent) / 100.0f; + float tTotalEUt = 0.0f; - tEmptySlots++; - if (tEmptySlots < outputItemCount) { - continue; + this.mEUt = 0; + + // Count recipes to do in parallel, consuming input items and fluids and considering input voltage limits + for (; parallelRecipes < aMaxParallelRecipes && tTotalEUt < (tVoltage - tRecipeEUt); parallelRecipes++) { + if (!tRecipe.isRecipeInputEqual(true, aFluidInputs, aItemInputs)) { + break; + } + tTotalEUt += tRecipeEUt; + } + + this.mEUt = (int)Math.ceil(tTotalEUt); + + if (parallelRecipes == 0) { + return false; + } + + this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000); + this.mEfficiencyIncrease = 10000; + + // Overclock + if (this.mEUt <= 16) { + this.mEUt = (this.mEUt * (1 << tTier - 1) * (1 << tTier - 1)); + this.mMaxProgresstime = (this.mMaxProgresstime / (1 << tTier - 1)); + } else { + while (this.mEUt <= gregtech.api.enums.GT_Values.V[(tTier - 1)]) { + this.mEUt *= 4; + this.mMaxProgresstime /= 2; + } + } + + if (this.mEUt > 0) { + this.mEUt = (-this.mEUt); + } + + this.mMaxProgresstime = Math.max(1, this.mMaxProgresstime); + + // Collect fluid outputs + FluidStack[] tOutputFluids = new FluidStack[tRecipe.mFluidOutputs.length]; + for (int h = 0; h < tRecipe.mFluidOutputs.length; h++) { + if (tRecipe.getFluidOutput(h) != null) { + tOutputFluids[h] = tRecipe.getFluidOutput(h).copy(); + tOutputFluids[h].amount *= parallelRecipes; + } + } + + // Collect output item types + ItemStack[] tOutputItems = new ItemStack[tRecipe.mOutputs.length]; + for (int h = 0; h < tRecipe.mOutputs.length; h++) { + if (tRecipe.getOutput(h) != null) { + tOutputItems[h] = tRecipe.getOutput(h).copy(); + tOutputItems[h].stackSize = 0; + } + } + + // Set output item stack sizes (taking output chance into account) + for (int f = 0; f < tOutputItems.length; f++) { + if (tRecipe.mOutputs[f] != null && tOutputItems[f] != null) { + for (int g = 0; g < parallelRecipes; g++) { + if (getBaseMetaTileEntity().getRandomNumber(aOutputChanceRoll) < tRecipe.getOutputChance(f)) + tOutputItems[f].stackSize += tRecipe.mOutputs[f].stackSize; } + } + } - tValidOutputHatches++; - foundRoom = true; + tOutputItems = removeNulls(tOutputItems); + + // Sanitize item stack size, splitting any stacks greater than max stack size + List<ItemStack> splitStacks = new ArrayList<ItemStack>(); + for (ItemStack tItem : tOutputItems) { + while (tItem.getMaxStackSize() < tItem.stackSize) { + ItemStack tmp = tItem.copy(); + tmp.stackSize = tmp.getMaxStackSize(); + tItem.stackSize = tItem.stackSize - tItem.getMaxStackSize(); + splitStacks.add(tmp); } } - return tValidOutputHatches; + if (splitStacks.size() > 0) { + ItemStack[] tmp = new ItemStack[splitStacks.size()]; + tmp = splitStacks.toArray(tmp); + tOutputItems = ArrayUtils.addAll(tOutputItems, tmp); + } + + // Strip empty stacks + List<ItemStack> tSList = new ArrayList<ItemStack>(); + for (ItemStack tS : tOutputItems) { + if (tS.stackSize > 0) tSList.add(tS); + } + tOutputItems = tSList.toArray(new ItemStack[tSList.size()]); + + // Commit outputs + this.mOutputItems = tOutputItems; + this.mOutputFluids = tOutputFluids; + updateSlots(); + + // Play sounds (GT++ addition - GT multiblocks play no sounds) + startProcess(); + + return true; } public GT_Recipe reduceRecipeTimeByPercentage(final GT_Recipe tRecipe, |