Created
February 7, 2020 19:53
-
-
Save Rseding91/a1aad6c8667e1e56865dcb697d0d5083 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void CraftingMachine::update() | |
{ | |
assert(this->isActive()); | |
assert(!this->isToBeDeconstructed()); | |
/** Attempts to craft the current recipe (setting up the recipe if its a furnace) and returns the results of the attempt. */ | |
ProductionResult result = this->useRecipeOnSource(); | |
bool goToSleep = false; | |
switch (result) | |
{ | |
/** No power can mean 1 of 4 things: | |
* 1. Electric energy source that is out of power: there's no alarm condition for "power available" - sleep is not allowed. | |
* 2. Burner energy source that is out of power but has items to burn: 1 tick is required to burn the item - sleep is not allowed. | |
* 3. Burner energy source that is out of power and has no items to burn: sleep is allowed since postTransferHook will be called | |
* when fuel is inserted into the CraftingMachine's fuel inventory. | |
* 4. Heat energy source that is out of power: there's no alarm condition for "power available" - sleep is not allowed. */ | |
case ProductionResult::NoPower: | |
goToSleep = this->energySource->isBurnerSource() && !this->energySource->hasEnergyPotentially(); | |
break; | |
/** No recipe can mean 1 of 2 things: | |
* 1. A furnace that can't smelt what ever may be in its inventory (invalid item or not enough for the recipe) : sleep is allowed | |
* since postTransferHook will be called when more items are inserted into the input inventory. | |
* 2. A AssemblingMachine that has no recipe set: sleep is allowed since the recipe setup method will wake up the CraftingMachine.*/ | |
case ProductionResult::NoRecipe: | |
if (this->isFurnace()) | |
this->inputWakeUpList.alarm(); | |
[[fallthrough]]; | |
/** No item inventory - rare but if it happens the CraftingMachine can't do work so it's put to sleep. */ | |
case ProductionResult::NoItemInventory: | |
/** No fluid inventory - rare but if it happens the CraftingMachine can't do work so it's put to sleep. */ | |
case ProductionResult::NoFluidInventory: | |
/** Item product overload - too many items in the output inventory to finish the current recipe-in-progress: sleep is allowed | |
* since postTransferHook will be called when the output inventory count is reduced.*/ | |
case ProductionResult::ItemProductionOverload: | |
/** Item ingredient shortage - not enough items in the input inventory to craft the recipe: sleep is allowed | |
* since postTransferHook will be called when the input inventory count is increased.*/ | |
case ProductionResult::ItemIngredientShortage: | |
this->flags.setShowWorkingVisualizations(false); | |
goToSleep = true; | |
break; | |
case ProductionResult::FluidProductionOverload: | |
case ProductionResult::FluidIngredientShortage: | |
this->flags.setShowWorkingVisualizations(false); | |
break; | |
case ProductionResult::Success: | |
{ | |
uint32_t tick = this->getMap().entityTick; | |
this->workingVisualisationFadeout = Math::min(uint8_t(this->getCurrentFadeout(tick) + 1), WorkingVisualisations::FADOUT_TICK_COUNT); | |
this->tickOfLastFadoutValue = tick; | |
break; | |
} | |
case ProductionResult::None: | |
break; | |
} | |
bool isOutputOverload = false; | |
if (this->hasRecipe()) | |
{ | |
const Recipe* recipe = this->getRecipe(); | |
if (recipe->hasItemIngredient() && recipe->hasFluidProduct() && | |
this->isFluidBoxManagerActive()) | |
{ | |
ProductionResult outputOverloadStatus = this->hasProductOverload(*this->getRecipe()); | |
/** If the CraftingMachine had a fluid product overload last update and it no longer does | |
* the inputWakeUpList needs to be alarmed: input inserters will not input during a product overload.*/ | |
if (this->getRecipe()->hasItemIngredient() && | |
outputOverloadStatus == ProductionResult::Success && | |
this->flags.getFluidOutputOverloadedLastUpdate()) | |
this->inputWakeUpList.alarm(); | |
isOutputOverload = (outputOverloadStatus == ProductionResult::FluidProductionOverload); | |
} | |
} | |
this->flags.setFluidOutputOverloadedLastUpdate(isOutputOverload); | |
// we check against current version of outputOverload | |
// there was a bug earlier when instead of current overload status we would check one made directly after FluidBox::update | |
// however useRecipeOnSource can change outputOverloadStatus (by pouring products into the output fluidbox) | |
// while at the same time returning ItemIngredientShortage hence resulting in sleep request | |
if (goToSleep && !isOutputOverload) | |
{ | |
this->flags.setShowWorkingVisualizations(false); | |
this->tryToGetToSleep(result); | |
} | |
// Only burner and fluid energy sources require manual updating | |
if (this->energySource->isBurnerSource() || this->energySource->isFluidSource()) | |
this->energySource->update(this, result == ProductionResult::Success || result == ProductionResult::NoPower); | |
if (this->isActive()) | |
this->setHadFullUpdateTick(); | |
else | |
this->clearHadFullUpdateTick(); | |
} | |
ProductionResult CraftingMachine::useRecipeOnSource() | |
{ | |
prefetch(this->energySource); | |
prefetch(static_cast<char*>(static_cast<void*>(this->energySource)) + hardware_constructive_interference_size); | |
if (!this->hasRecipe()) | |
return ProductionResult::NoRecipe; | |
const Recipe* recipe = this->getRecipe(); | |
const double recipeEnergy = recipe->getEnergyRequired(); | |
// Use productivity first because it can have > 100% of normal energy. | |
// e.g. - 200% productivity of a recipe that produces 1 per tick would mean 2 bonus per tick | |
while (this->bonusProduction + GlobalContext::minimumCountableDoubleValue >= recipeEnergy) | |
{ | |
ProductionResult useBonusResults = this->useBonusProduction(*recipe); | |
if (useBonusResults != ProductionResult::Success) | |
return useBonusResults; | |
if (!this->shouldContinueCrafting()) | |
return useBonusResults; | |
} | |
if (this->energyStoredInProduct >= recipeEnergy) | |
{ | |
ProductionResult useStoredResults = this->useEnergyStoredInProduct(*recipe); | |
if (useStoredResults != ProductionResult::Success) | |
return useStoredResults; | |
if (!this->shouldContinueCrafting()) | |
return useStoredResults; | |
} | |
bool takeIngredients = false; | |
if (this->energyStoredInProduct == 0) | |
{ | |
ProductionResult canTakeResults = this->canTakeIngredients(*recipe); | |
// The canTakeIngredients could update this->recipeID. | |
// I have to update the local recipe pointer if that happened. | |
if (recipe->getID() != this->recipeID) | |
recipe = this->getRecipe(); | |
if (canTakeResults != ProductionResult::Success) | |
return canTakeResults; | |
takeIngredients = true; | |
} | |
double performance = this->extractEnergyAndPollute(); | |
if (performance <= 0) | |
{ | |
this->flags.setShowWorkingVisualizations(false); | |
return ProductionResult::NoPower; | |
} | |
else | |
{ | |
if (takeIngredients) | |
{ | |
this->takeIngredients(*recipe); | |
this->energyStoredInProduct += this->extraEnergyForProduct; | |
this->extraEnergyForProduct = 0; | |
} | |
this->setupWorkingVisualisationFrames(performance); | |
} | |
return ProductionResult::Success; | |
} | |
void CraftingMachine::tryToGetToSleep(ProductionResult sleepReason) | |
{ | |
assert(sleepReason != ProductionResult::Success); | |
// Don't sleep if there's no recipe (furnace with fluid inputs) or fluid in the output fluidboxes (assembling machine with fluid to output) | |
if (this->isFluidBoxManagerActive() && (sleepReason == ProductionResult::NoRecipe || this->fluidBoxManager->hasFluidInOutputFluidboxes())) | |
return; | |
this->sleepReason = sleepReason; | |
this->setActive(false, *this); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment