2014-07-07 21:31:10 +02:00
package com.pahimar.ee3.exchange ;
2014-06-14 21:40:45 +02:00
2016-05-18 19:53:13 +02:00
import com.google.common.collect.ImmutableMap ;
2014-07-14 18:04:20 +02:00
import com.google.common.collect.ImmutableSortedMap ;
2016-05-18 19:53:13 +02:00
import com.pahimar.ee3.api.event.EnergyValueEvent ;
2015-05-07 19:45:06 +02:00
import com.pahimar.ee3.api.exchange.EnergyValue ;
import com.pahimar.ee3.api.exchange.IEnergyValueProvider ;
2016-05-16 21:06:40 +02:00
import com.pahimar.ee3.handler.ConfigurationHandler ;
2014-07-07 21:31:10 +02:00
import com.pahimar.ee3.recipe.RecipeRegistry ;
2016-05-20 19:56:53 +02:00
import com.pahimar.ee3.reference.Comparators ;
import com.pahimar.ee3.util.FilterUtils ;
2015-05-07 20:47:54 +02:00
import com.pahimar.ee3.util.LoaderHelper ;
2015-05-02 20:07:01 +02:00
import com.pahimar.ee3.util.LogHelper ;
import com.pahimar.ee3.util.SerializationHelper ;
2015-01-27 05:17:32 +01:00
import cpw.mods.fml.common.FMLCommonHandler ;
2015-05-07 20:47:54 +02:00
import cpw.mods.fml.common.Loader ;
2014-06-14 21:40:45 +02:00
import net.minecraft.item.Item ;
import net.minecraft.item.ItemStack ;
2016-05-18 19:53:13 +02:00
import net.minecraftforge.fluids.FluidContainerRegistry ;
2014-06-14 21:40:45 +02:00
import net.minecraftforge.oredict.OreDictionary ;
2015-11-19 21:24:40 +01:00
import org.apache.logging.log4j.Marker ;
import org.apache.logging.log4j.MarkerManager ;
2014-06-14 21:40:45 +02:00
2016-05-19 02:54:04 +02:00
import java.io.File ;
import java.io.FileNotFoundException ;
2014-06-14 21:40:45 +02:00
import java.util.* ;
2016-05-18 19:53:13 +02:00
import static com.pahimar.ee3.api.exchange.EnergyValueRegistryProxy.Phase ;
2014-06-14 21:40:45 +02:00
2016-05-18 19:53:13 +02:00
public class EnergyValueRegistry {
2014-06-14 21:40:45 +02:00
2016-05-18 19:53:13 +02:00
public static final EnergyValueRegistry INSTANCE = new EnergyValueRegistry ( ) ;
2016-05-11 21:59:52 +02:00
2016-05-18 19:53:13 +02:00
private ImmutableSortedMap < WrappedStack , EnergyValue > stackValueMap ;
2016-05-20 19:56:53 +02:00
private ImmutableSortedMap < EnergyValue , Set < WrappedStack > > valueStackMap ;
2014-06-14 21:40:45 +02:00
2016-05-18 19:53:13 +02:00
private final Map < WrappedStack , EnergyValue > preCalculationStackValueMap ;
private final Map < WrappedStack , EnergyValue > postCalculationStackValueMap ;
private transient SortedSet < WrappedStack > uncomputedStacks ;
2016-05-25 05:12:49 +02:00
private transient boolean shouldSave ;
private transient boolean valuesNeedRegeneration ;
2014-06-14 21:40:45 +02:00
2016-05-18 19:53:13 +02:00
public static File energyValuesDirectory ;
public static File energyValuesFile ;
public static File preCalculationValuesFile ;
public static File postCalculationValuesFile ;
2014-06-14 21:40:45 +02:00
2016-05-18 19:53:13 +02:00
public static final Marker ENERGY_VALUE_MARKER = MarkerManager . getMarker ( " EE3_ENERGY_VALUE " , LogHelper . MOD_MARKER ) ;
2014-06-14 21:40:45 +02:00
2016-05-18 19:53:13 +02:00
private EnergyValueRegistry ( ) {
ImmutableSortedMap . Builder < WrappedStack , EnergyValue > stackMapBuilder = ImmutableSortedMap . naturalOrder ( ) ;
stackValueMap = stackMapBuilder . build ( ) ;
preCalculationStackValueMap = new TreeMap < > ( ) ;
postCalculationStackValueMap = new TreeMap < > ( ) ;
uncomputedStacks = new TreeSet < > ( ) ;
2016-05-25 05:12:49 +02:00
shouldSave = true ;
2016-05-18 19:53:13 +02:00
}
/ * *
* Returns an { @link EnergyValue } for a { @link Object } in the provided { @link Map > } of { @link WrappedStack } s mapped
* to EnergyValues
*
* < p > The order of checking is as follows ; < / p >
* < ol >
* < li > { @link ItemStack } s whose { @link Item } s implement { @link IEnergyValueProvider } < / li >
* < li > Direct EnergyValue mapping of the provided Object in the provided Map < / li >
* < li > The following criteria are only checked ( in order ) in the event that this is a non - strict query ;
* < ol >
* < li >
* ItemStacks that are part of an { @link OreDictionary } entry are checked to see if
* < strong > all < / strong > Ores they are registered to have the same non - null EnergyValue assigned to
* it
* < ul >
* < li >
* e . g . , ItemStack X is associated with OreDictionary entries A , B and C . An EnergyValue
* would be returned for X only if A , B and C all had the same non - null EnergyValue
* < / li >
* < / ul >
* < / li >
* < li >
* ItemStacks are checked to see if there exist { @link OreDictionary # WILDCARD_VALUE } equivalents
* < / li >
* < li >
* { @link OreStack } s are checked to see if all members of the OreDictionary entry represented by the
* OreStack have the same non - null EnergyValue ( similar to the case for ItemStacks above )
* < / li >
* < / ol >
* < / li >
* < / ol >
*
* @param valueMap a { @link Map } of { @link EnergyValue } ' s mapped to { @link WrappedStack } ' s
* @param object the { @link Object } that is being checked for a corresponding { @link EnergyValue }
* @param strict whether this is a strict ( e . g . , only looking for direct value assignment vs associative value
* assignments ) query or not
* @return an { @link EnergyValue } if there is one to be found for the provided { @link Object } in the provided Map , null otherwise
* /
2016-05-20 19:56:53 +02:00
public static EnergyValue getEnergyValue ( Map < WrappedStack , EnergyValue > valueMap , Object object , boolean strict ) {
2016-05-18 19:53:13 +02:00
if ( WrappedStack . canBeWrapped ( object ) ) {
WrappedStack wrappedStack = WrappedStack . wrap ( object , 1 ) ;
Object wrappedObject = wrappedStack . getWrappedObject ( ) ;
if ( wrappedObject instanceof ItemStack & & ( ( ItemStack ) wrappedObject ) . getItem ( ) instanceof IEnergyValueProvider & & ! strict ) {
EnergyValue energyValue = ( ( IEnergyValueProvider ) ( ( ItemStack ) wrappedObject ) . getItem ( ) ) . getEnergyValue ( ( ( ItemStack ) wrappedObject ) ) ;
if ( energyValue ! = null & & Float . compare ( energyValue . getValue ( ) , 0f ) > 0 ) {
return energyValue ;
}
2014-06-14 21:40:45 +02:00
}
2016-05-18 19:53:13 +02:00
if ( valueMap ! = null & & ! valueMap . isEmpty ( ) ) {
2014-06-14 21:40:45 +02:00
2016-05-18 19:53:13 +02:00
// First check for a direct energy value mapping to the wrapped object
2016-05-27 22:03:14 +02:00
/ * *
* FIXME If the object being checked has a WILD_CARD meta value , then it will match any similar object .
* We must ensure that it returns the LOWEST possible value from the map
* /
2016-05-18 19:53:13 +02:00
if ( valueMap . containsKey ( wrappedStack ) ) {
return valueMap . get ( wrappedStack ) ;
}
else if ( ! strict ) {
2015-03-05 05:31:43 +01:00
2016-05-18 19:53:13 +02:00
if ( wrappedObject instanceof ItemStack ) {
2014-07-07 17:22:21 +02:00
2016-05-18 19:53:13 +02:00
ItemStack unValuedItemStack = ItemStack . copyItemStack ( ( ItemStack ) wrappedObject ) ;
EnergyValue minEnergyValue = null ;
2015-04-19 21:01:35 +02:00
2016-05-18 19:53:13 +02:00
int [ ] oreIds = OreDictionary . getOreIDs ( unValuedItemStack ) ;
if ( oreIds . length > 0 ) {
2015-04-19 21:01:35 +02:00
2016-05-18 19:53:13 +02:00
EnergyValue energyValue = null ;
boolean allHaveSameValue = true ;
2015-04-19 21:01:35 +02:00
2016-05-18 19:53:13 +02:00
for ( int oreId : oreIds ) {
String oreName = OreDictionary . getOreName ( oreId ) ;
2015-04-19 21:01:35 +02:00
2016-05-18 19:53:13 +02:00
if ( ! " Unknown " . equalsIgnoreCase ( oreName ) ) {
2015-04-14 04:27:11 +02:00
2015-04-19 21:01:35 +02:00
WrappedStack oreStack = WrappedStack . wrap ( new OreStack ( oreName ) ) ;
2016-05-18 19:53:13 +02:00
if ( oreStack ! = null & & valueMap . containsKey ( oreStack ) ) {
if ( energyValue = = null ) {
energyValue = valueMap . get ( oreStack ) ;
2015-04-19 21:01:35 +02:00
}
2016-05-18 19:53:13 +02:00
else if ( ! energyValue . equals ( valueMap . get ( oreStack ) ) ) {
allHaveSameValue = false ;
2015-04-19 21:01:35 +02:00
}
}
2016-05-18 19:53:13 +02:00
else {
allHaveSameValue = false ;
2015-04-19 21:01:35 +02:00
}
}
2016-05-18 19:53:13 +02:00
else {
allHaveSameValue = false ;
2015-04-19 21:01:35 +02:00
}
}
2016-05-18 19:53:13 +02:00
if ( allHaveSameValue ) {
2015-04-19 21:01:35 +02:00
return energyValue ;
2015-04-14 04:27:11 +02:00
}
}
2016-05-18 19:53:13 +02:00
else {
for ( WrappedStack valuedWrappedStack : valueMap . keySet ( ) ) {
if ( valuedWrappedStack . getWrappedObject ( ) instanceof ItemStack ) {
if ( Item . getIdFromItem ( ( ( ItemStack ) valuedWrappedStack . getWrappedObject ( ) ) . getItem ( ) ) = = Item . getIdFromItem ( unValuedItemStack . getItem ( ) ) ) {
ItemStack valuedItemStack = ( ItemStack ) valuedWrappedStack . getWrappedObject ( ) ;
if ( valuedItemStack . getItemDamage ( ) = = OreDictionary . WILDCARD_VALUE | | unValuedItemStack . getItemDamage ( ) = = OreDictionary . WILDCARD_VALUE ) {
2014-06-14 21:40:45 +02:00
2016-05-18 19:53:13 +02:00
EnergyValue energyValue = valueMap . get ( valuedWrappedStack ) ;
if ( energyValue . compareTo ( minEnergyValue ) < 0 ) {
minEnergyValue = energyValue ;
2014-06-14 21:40:45 +02:00
}
}
}
2014-07-14 20:30:50 +02:00
}
2014-06-14 21:40:45 +02:00
}
}
}
2016-05-18 19:53:13 +02:00
else if ( wrappedObject instanceof OreStack ) {
2015-04-19 21:01:35 +02:00
OreStack oreStack = ( OreStack ) wrappedObject ;
2016-05-18 19:53:13 +02:00
List < ItemStack > itemStacks = OreDictionary . getOres ( oreStack . oreName ) ;
if ( ! itemStacks . isEmpty ( ) ) {
2015-04-19 21:01:35 +02:00
EnergyValue energyValue = null ;
2016-05-18 19:53:13 +02:00
boolean allHaveSameValue = true ;
for ( ItemStack itemStack : itemStacks ) {
WrappedStack wrappedItemStack = WrappedStack . wrap ( itemStack , 1 ) ;
if ( wrappedItemStack ! = null & & valueMap . containsKey ( wrappedItemStack ) ) {
if ( energyValue = = null ) {
energyValue = valueMap . get ( wrappedItemStack ) ;
2015-04-19 21:01:35 +02:00
}
2016-05-18 19:53:13 +02:00
else if ( ! energyValue . equals ( valueMap . get ( wrappedItemStack ) ) ) {
allHaveSameValue = false ;
2015-04-19 21:01:35 +02:00
}
}
2016-05-18 19:53:13 +02:00
else {
allHaveSameValue = false ;
2015-04-19 21:01:35 +02:00
}
}
2016-05-18 19:53:13 +02:00
if ( allHaveSameValue ) {
2015-04-19 21:01:35 +02:00
return energyValue ;
}
}
}
2014-06-14 21:40:45 +02:00
}
}
}
return null ;
}
2016-05-18 19:53:13 +02:00
/ * *
2016-05-20 03:10:55 +02:00
* Calculates an { @link EnergyValue } for the provided { @link WrappedStack } output from the provided
* { @link Collection } of WrappedStack inputs and { @link Map } of energy value mappings to objects . We calculate the
* energy value for the output by , for each input , summing the input ' s energy value * the input ' s stack size . That
* sum is then divided by the stack size of the output . If < strong > any < / strong > of the inputs do not have an energy
* value then no energy value can be calculated for the output - therefore we return null
2016-05-18 19:53:13 +02:00
*
* @param valueMap a { @link Map } of { @link EnergyValue } ' s mapped to { @link WrappedStack } ' s
* @param wrappedOutput the { @link WrappedStack } output for that the inputs " create "
2016-05-20 03:10:55 +02:00
* @param wrappedInputs a { @link Collection } of { @link WrappedStack } s that " create " the output
2016-05-18 19:53:13 +02:00
* @return an { @link EnergyValue } if there is one that can be calculated , null otherwise
* /
2016-05-20 03:10:55 +02:00
private static EnergyValue computeFromInputs ( Map < WrappedStack , EnergyValue > valueMap , WrappedStack wrappedOutput , Collection < WrappedStack > wrappedInputs ) {
2014-08-29 22:25:31 +02:00
2016-05-18 19:53:13 +02:00
float sumOfValues = 0f ;
2014-07-14 04:05:27 +02:00
2016-05-18 19:53:13 +02:00
for ( WrappedStack wrappedInput : wrappedInputs ) {
2014-09-12 22:11:18 +02:00
2016-05-18 19:53:13 +02:00
EnergyValue inputValue ;
int stackSize = Integer . MIN_VALUE ;
if ( wrappedInput . getWrappedObject ( ) instanceof ItemStack ) {
2014-07-14 04:05:27 +02:00
2016-05-18 19:53:13 +02:00
ItemStack inputItemStack = ( ItemStack ) wrappedInput . getWrappedObject ( ) ;
2014-07-22 03:43:04 +02:00
2016-05-18 19:53:13 +02:00
// Check if we are dealing with a potential fluid
if ( FluidContainerRegistry . getFluidForFilledItem ( inputItemStack ) ! = null ) {
2014-07-14 04:05:27 +02:00
2016-05-18 19:53:13 +02:00
if ( inputItemStack . getItem ( ) . getContainerItem ( inputItemStack ) ! = null ) {
stackSize = FluidContainerRegistry . getFluidForFilledItem ( inputItemStack ) . amount * wrappedInput . getStackSize ( ) ;
inputValue = getEnergyValue ( valueMap , FluidContainerRegistry . getFluidForFilledItem ( inputItemStack ) , false ) ;
}
else {
inputValue = getEnergyValue ( valueMap , wrappedInput , false ) ;
2014-07-14 04:05:27 +02:00
}
}
2016-05-18 19:53:13 +02:00
else if ( inputItemStack . getItem ( ) . getContainerItem ( inputItemStack ) ! = null ) {
2014-07-14 04:05:27 +02:00
2016-05-18 19:53:13 +02:00
ItemStack inputContainerItemStack = inputItemStack . getItem ( ) . getContainerItem ( inputItemStack ) ;
if ( getEnergyValue ( valueMap , inputItemStack , false ) ! = null & & getEnergyValue ( valueMap , inputContainerItemStack , false ) ! = null ) {
float itemStackValue = getEnergyValue ( valueMap , inputItemStack , false ) . getValue ( ) ;
float containerStackValue = getEnergyValue ( valueMap , inputContainerItemStack , false ) . getValue ( ) ;
inputValue = new EnergyValue ( itemStackValue - containerStackValue ) ;
2014-07-14 04:05:27 +02:00
}
2016-05-18 19:53:13 +02:00
else {
inputValue = new EnergyValue ( 0 ) ;
2014-07-14 04:05:27 +02:00
}
}
2016-05-18 19:53:13 +02:00
else if ( ! inputItemStack . getItem ( ) . doesContainerItemLeaveCraftingGrid ( inputItemStack ) ) {
inputValue = new EnergyValue ( 0 ) ;
}
else if ( OreDictionary . getOreIDs ( inputItemStack ) . length > 0 ) {
inputValue = getEnergyValue ( valueMap , wrappedInput , true ) ;
}
else {
inputValue = getEnergyValue ( valueMap , wrappedInput , false ) ;
2015-04-14 04:27:11 +02:00
}
2014-07-14 04:05:27 +02:00
}
2016-05-18 19:53:13 +02:00
else if ( wrappedInput . getWrappedObject ( ) instanceof OreStack ) {
2015-06-10 05:25:40 +02:00
2016-05-18 19:53:13 +02:00
OreStack inputOreStack = ( OreStack ) wrappedInput . getWrappedObject ( ) ;
inputValue = getEnergyValue ( valueMap , wrappedInput , false ) ;
for ( ItemStack itemStack : OreDictionary . getOres ( inputOreStack . oreName ) ) {
if ( ! itemStack . getItem ( ) . doesContainerItemLeaveCraftingGrid ( itemStack ) ) {
inputValue = new EnergyValue ( 0 ) ;
}
}
2015-06-10 05:25:40 +02:00
}
2016-05-18 19:53:13 +02:00
else {
inputValue = getEnergyValue ( valueMap , wrappedInput , false ) ;
}
if ( inputValue ! = null ) {
if ( stackSize = = Integer . MIN_VALUE ) {
stackSize = wrappedInput . getStackSize ( ) ;
}
2014-07-14 04:05:27 +02:00
2016-05-18 19:53:13 +02:00
sumOfValues + = inputValue . getValue ( ) * stackSize ;
}
else {
return null ;
2015-04-14 04:27:11 +02:00
}
}
2014-09-12 22:11:18 +02:00
2016-05-18 19:53:13 +02:00
return EnergyValue . factor ( new EnergyValue ( sumOfValues ) , wrappedOutput . getStackSize ( ) ) ;
}
2014-07-14 18:04:20 +02:00
2016-05-18 19:53:13 +02:00
/ * *
* Returns an { @link ImmutableMap } containing the current energy value mappings
*
* @return an { @link ImmutableMap } containing the current energy value mappings
* /
public ImmutableMap < WrappedStack , EnergyValue > getEnergyValues ( ) {
return stackValueMap ;
}
2015-02-16 03:13:35 +01:00
2016-05-18 19:53:13 +02:00
/ * *
* Returns a { @link Map } containing the pre - calculation energy value mappings
*
* @return a { link Map } containing the pre - calculation energy value mappings
* /
public Map < WrappedStack , EnergyValue > getPreCalculationStackValueMap ( ) {
return preCalculationStackValueMap ;
}
2015-06-10 05:25:40 +02:00
2016-05-18 19:53:13 +02:00
/ * *
* Returns a { @link Map } containing the post - calculation energy value mappings
*
* @return a { @link Map } containing the post - calculation energy value mappings
* /
public Map < WrappedStack , EnergyValue > getPostCalculationStackValueMap ( ) {
return postCalculationStackValueMap ;
2015-02-16 03:13:35 +01:00
}
2016-05-18 19:53:13 +02:00
/ * *
* Checks if there exists an { @link EnergyValue } associated with the provided { @link Object } .
*
* @param object the { @link Object } that is being checked for a corresponding { @link EnergyValue }
* @return true if the provided object has an energy value , false otherwise
* /
public boolean hasEnergyValue ( Object object ) {
return hasEnergyValue ( object , false ) ;
2014-07-14 04:05:27 +02:00
}
2016-05-18 19:53:13 +02:00
/ * *
* Checks if there exists an { @link EnergyValue } associated with the provided { @link Object }
*
* @param object the { @link Object } that is being checked for a corresponding { @link EnergyValue }
* @param strict whether this is a strict ( e . g . , only looking for direct value assignment vs associative value
* assignments ) query or not
* @return true if the provided object has an energy value , false otherwise
* /
public boolean hasEnergyValue ( Object object , boolean strict ) {
return getEnergyValue ( object , strict ) ! = null ;
}
2015-06-10 05:25:40 +02:00
2016-05-18 19:53:13 +02:00
/ * *
* Returns an { @link EnergyValue } associated with the provided { @link Object } ( if there is one )
*
* @param object the { @link Object } that is being checked for a corresponding { @link EnergyValue }
* @return an { @link EnergyValue } if there is one to be found , null otherwise
* /
public EnergyValue getEnergyValue ( Object object ) {
return getEnergyValue ( object , false ) ;
}
/ * *
* Returns an { @link EnergyValue } associated with the provided { @link Object } ( if there is one )
*
* @param object the { @link Object } that is being checked for a corresponding { @link EnergyValue }
* @param strict whether this is a strict ( e . g . , only looking for direct value assignment vs associative value
* assignments ) query or not
* @return an { @link EnergyValue } if there is one to be found , null otherwise
* /
public EnergyValue getEnergyValue ( Object object , boolean strict ) {
return getEnergyValue ( stackValueMap , object , strict ) ;
}
/ * *
* Returns an { @link EnergyValue } associated with the provided { @link Object } ( if there is one )
*
* @param object the { @link Object } that is being checked for a corresponding { @link EnergyValue }
* @param strict whether this is a strict ( e . g . , only looking for direct value assignment vs associative value
* assignments ) query or not
* @return an { @link EnergyValue } if there is one to be found , null otherwise
* /
public EnergyValue getEnergyValueForStack ( Object object , boolean strict ) {
2014-07-14 04:05:27 +02:00
2016-05-18 19:53:13 +02:00
WrappedStack wrappedObject = WrappedStack . wrap ( object ) ;
if ( wrappedObject ! = null & & getEnergyValue ( object , strict ) ! = null ) {
return new EnergyValue ( getEnergyValue ( object , strict ) . getValue ( ) * wrappedObject . getStackSize ( ) ) ;
2014-07-14 04:05:27 +02:00
}
2016-05-18 19:53:13 +02:00
return null ;
2014-07-14 04:05:27 +02:00
}
2016-05-18 19:53:13 +02:00
/ * *
* TODO Finish JavaDoc
*
* @param start
* @param finish
* @return
* /
2016-05-20 19:56:53 +02:00
public Set < ItemStack > getStacksInRange ( Number start , Number finish ) {
2014-06-14 21:40:45 +02:00
return getStacksInRange ( new EnergyValue ( start ) , new EnergyValue ( finish ) ) ;
}
2016-05-18 19:53:13 +02:00
/ * *
* TODO Finish JavaDoc
*
2016-05-20 19:56:53 +02:00
* @param lowerBound
* @param upperBound
2016-05-18 19:53:13 +02:00
* @return
* /
2016-05-20 19:56:53 +02:00
public Set < ItemStack > getStacksInRange ( EnergyValue lowerBound , EnergyValue upperBound ) {
2014-07-14 04:05:27 +02:00
2016-05-20 19:56:53 +02:00
Set < ItemStack > filteredItemStacks = new TreeSet < > ( Comparators . ENERGY_VALUE_ITEM_STACK_COMPARATOR ) ;
2014-06-14 21:40:45 +02:00
2016-05-20 19:56:53 +02:00
Set < ItemStack > greaterThanLowerBound = getStacksInRange ( getEnergyValues ( ) , lowerBound , false ) ;
Set < ItemStack > lesserThanUpperBound = getStacksInRange ( getEnergyValues ( ) , upperBound , true ) ;
2016-05-18 19:53:13 +02:00
2016-05-20 19:56:53 +02:00
if ( ! greaterThanLowerBound . isEmpty ( ) & & ! lesserThanUpperBound . isEmpty ( ) ) {
2014-06-14 21:40:45 +02:00
2016-05-20 19:56:53 +02:00
for ( ItemStack itemStack : greaterThanLowerBound ) {
if ( lesserThanUpperBound . contains ( itemStack ) ) {
filteredItemStacks . add ( itemStack ) ;
}
}
}
else if ( ! greaterThanLowerBound . isEmpty ( ) ) {
return greaterThanLowerBound ;
}
else if ( ! lesserThanUpperBound . isEmpty ( ) ) {
return lesserThanUpperBound ;
}
return filteredItemStacks ;
}
/ * *
* TODO Finish JavaDoc
*
* @param valueMap
* @param energyValueBound
* @param isUpperBound
* @return
* /
private static Set < ItemStack > getStacksInRange ( Map < WrappedStack , EnergyValue > valueMap , EnergyValue energyValueBound , boolean isUpperBound ) {
2014-06-14 21:40:45 +02:00
2016-05-27 22:03:14 +02:00
Set itemStacks = filterForItemStacks ( valueMap . keySet ( ) ) ;
2015-03-23 12:36:32 +01:00
2016-05-20 19:56:53 +02:00
if ( valueMap ! = null ) {
if ( energyValueBound ! = null ) {
if ( isUpperBound ) {
return FilterUtils . filterByEnergyValue ( valueMap , itemStacks , energyValueBound , FilterUtils . ValueFilterType . VALUE_LOWER_THAN_BOUND , Comparators . ENERGY_VALUE_ITEM_STACK_COMPARATOR ) ;
2015-03-23 12:36:32 +01:00
}
2016-05-18 19:53:13 +02:00
else {
2016-05-20 19:56:53 +02:00
return FilterUtils . filterByEnergyValue ( valueMap , itemStacks , energyValueBound , FilterUtils . ValueFilterType . VALUE_GREATER_THAN_BOUND , Comparators . ENERGY_VALUE_ITEM_STACK_COMPARATOR ) ;
2014-06-14 21:40:45 +02:00
}
}
}
2016-05-20 19:56:53 +02:00
return new TreeSet < > ( Collections . EMPTY_SET ) ;
2014-06-14 21:40:45 +02:00
}
2014-07-25 04:03:36 +02:00
2016-05-20 19:56:53 +02:00
2016-05-18 19:53:13 +02:00
/ * *
* Sets an { @link EnergyValue } for the provided { @link Object } ( if it can be wrapped in a { @link WrappedStack } .
* Depending on whether or not this is a pre - calculation value assignment it ' s also possible for the calculated
* energy value map to be recomputed to take into account the new mapping .
*
* @param object the object the energy value is being assigned for
* @param energyValue the energy value being setEnergyValue on the object
* @param phase the { @link Phase } of energy value assignment to set this value for
* /
public void setEnergyValue ( Object object , EnergyValue energyValue , Phase phase ) {
setEnergyValue ( object , energyValue , phase , false ) ;
}
/ * *
* Sets an { @link EnergyValue } for the provided { @link Object } ( if it can be wrapped in a { @link WrappedStack } .
* Depending on whether or not this is a pre - calculation value assignment it ' s also possible for the calculated
* energy value map to be recomputed to take into account the new mapping .
*
* @param object the object the energy value is being assigned for
* @param energyValue the energy value being setEnergyValue on the object
* @param phase the { @link Phase } of energy value assignment to set this value for
* @param doRegenValues whether or not the energy value map needs recomputing . Only an option if the energy value
* is being assigned in the < code > PRE_CALCULATION < / code > phase
* /
public void setEnergyValue ( Object object , EnergyValue energyValue , Phase phase , boolean doRegenValues ) {
if ( WrappedStack . canBeWrapped ( object ) & & energyValue ! = null & & Float . compare ( energyValue . getValue ( ) , 0f ) > 0 ) {
WrappedStack wrappedStack = WrappedStack . wrap ( object , 1 ) ;
EnergyValue factoredEnergyValue = EnergyValue . factor ( energyValue , wrappedStack . getStackSize ( ) ) ;
if ( phase = = Phase . PRE_CALCULATION ) {
if ( ! FMLCommonHandler . instance ( ) . bus ( ) . post ( new EnergyValueEvent . SetEnergyValueEvent ( wrappedStack , factoredEnergyValue , Phase . PRE_CALCULATION ) ) ) {
preCalculationStackValueMap . put ( wrappedStack , factoredEnergyValue ) ;
if ( doRegenValues ) {
compute ( ) ;
}
2016-05-25 05:12:49 +02:00
else {
valuesNeedRegeneration = true ;
}
2016-05-18 19:53:13 +02:00
}
}
else if ( ! FMLCommonHandler . instance ( ) . bus ( ) . post ( new EnergyValueEvent . SetEnergyValueEvent ( wrappedStack , factoredEnergyValue , Phase . POST_CALCULATION ) ) ) {
TreeMap < WrappedStack , EnergyValue > valueMap = new TreeMap < > ( stackValueMap ) ;
valueMap . put ( wrappedStack , energyValue ) ;
ImmutableSortedMap . Builder < WrappedStack , EnergyValue > stackMappingsBuilder = ImmutableSortedMap . naturalOrder ( ) ;
stackValueMap = stackMappingsBuilder . putAll ( valueMap ) . build ( ) ;
postCalculationStackValueMap . put ( wrappedStack , factoredEnergyValue ) ;
}
2014-08-29 22:25:31 +02:00
2016-05-18 19:53:13 +02:00
if ( ConfigurationHandler . Settings . energyValueDebugLoggingEnabled ) {
LogHelper . info ( ENERGY_VALUE_MARKER , " [{}] Mod '{}' set a {} value of {} on object '{}' with doRegen = {} " , LoaderHelper . getLoaderState ( ) , Loader . instance ( ) . activeModContainer ( ) . getModId ( ) , phase , energyValue , wrappedStack , doRegenValues ) ;
}
2014-08-29 22:25:31 +02:00
}
}
2016-05-25 17:01:07 +02:00
/ * *
* TODO Finish JavaDoc
*
* @param shouldSave
* /
2016-05-25 05:12:49 +02:00
public void setShouldSave ( boolean shouldSave ) {
this . shouldSave = shouldSave ;
}
2016-05-18 19:53:13 +02:00
/ * *
* TODO Finish JavaDoc
*
* This is where the magic happens
* /
public void compute ( ) {
2014-09-10 04:52:46 +02:00
2016-05-25 05:12:49 +02:00
valuesNeedRegeneration = false ;
2016-05-18 19:53:13 +02:00
// Initialize the "working copy" energy value map
final Map < WrappedStack , EnergyValue > stackValueMap = new TreeMap < > ( ) ;
uncomputedStacks = new TreeSet < > ( ) ;
2014-09-10 04:52:46 +02:00
2016-05-25 19:25:52 +02:00
// Load in pre calculation value assignments from file
Map < WrappedStack , EnergyValue > fileValueMap = null ;
try {
fileValueMap = SerializationHelper . readMapFromFile ( preCalculationValuesFile ) ;
}
catch ( FileNotFoundException e ) {
LogHelper . warn ( ENERGY_VALUE_MARKER , " No pre calculation energy values were loaded from file - could not find {} " , preCalculationValuesFile . getAbsolutePath ( ) ) ;
}
if ( fileValueMap ! = null ) {
for ( WrappedStack wrappedStack : fileValueMap . keySet ( ) ) {
if ( wrappedStack ! = null & & wrappedStack . getWrappedObject ( ) ! = null & & fileValueMap . get ( wrappedStack ) ! = null ) {
preCalculationStackValueMap . put ( wrappedStack , fileValueMap . get ( wrappedStack ) ) ;
}
}
}
2016-05-25 05:12:49 +02:00
2016-05-18 19:53:13 +02:00
// Add in all pre-calculation energy value mappings
preCalculationStackValueMap . keySet ( ) . stream ( )
. filter ( wrappedStack - > wrappedStack ! = null & & wrappedStack . getWrappedObject ( ) ! = null & & preCalculationStackValueMap . get ( wrappedStack ) ! = null )
. forEach ( wrappedStack - > stackValueMap . put ( wrappedStack , preCalculationStackValueMap . get ( wrappedStack ) ) ) ;
2014-09-16 18:08:16 +02:00
2016-05-18 19:53:13 +02:00
// Calculate values from the known methods to create items, and the pre-calculation value mappings
2016-05-27 22:03:14 +02:00
Map < WrappedStack , EnergyValue > computedStackValueMap = calculateStackValueMap ( stackValueMap ) ;
for ( WrappedStack wrappedStack : computedStackValueMap . keySet ( ) ) {
stackValueMap . put ( wrappedStack , computedStackValueMap . get ( wrappedStack ) ) ;
}
// stackValueMap.putAll(calculateStackValueMap(stackValueMap));
2014-09-16 18:08:16 +02:00
2016-05-25 19:25:52 +02:00
// Load in post calculation value assignments from file
fileValueMap = null ;
try {
fileValueMap = SerializationHelper . readMapFromFile ( postCalculationValuesFile ) ;
}
catch ( FileNotFoundException e ) {
LogHelper . warn ( ENERGY_VALUE_MARKER , " No post calculation energy values were loaded from file - could not find {} " , postCalculationValuesFile . getAbsolutePath ( ) ) ;
}
if ( fileValueMap ! = null ) {
for ( WrappedStack wrappedStack : fileValueMap . keySet ( ) ) {
if ( wrappedStack ! = null & & wrappedStack . getWrappedObject ( ) ! = null & & fileValueMap . get ( wrappedStack ) ! = null ) {
postCalculationStackValueMap . put ( wrappedStack , fileValueMap . get ( wrappedStack ) ) ;
}
}
}
2016-05-25 05:12:49 +02:00
2016-05-18 19:53:13 +02:00
// Add in all post-calculation energy value mappings
postCalculationStackValueMap . keySet ( ) . stream ( )
. filter ( wrappedStack - > wrappedStack ! = null & & wrappedStack . getWrappedObject ( ) ! = null & & postCalculationStackValueMap . get ( wrappedStack ) ! = null )
. forEach ( wrappedStack - > stackValueMap . put ( wrappedStack , postCalculationStackValueMap . get ( wrappedStack ) ) ) ;
2015-02-11 05:38:05 +01:00
2016-05-18 19:53:13 +02:00
// Bake the final calculated energy value maps
ImmutableSortedMap . Builder < WrappedStack , EnergyValue > stackMappingsBuilder = ImmutableSortedMap . naturalOrder ( ) ;
stackMappingsBuilder . putAll ( stackValueMap ) ;
this . stackValueMap = stackMappingsBuilder . build ( ) ;
calculateValueStackMap ( ) ;
2015-02-20 04:09:10 +01:00
2016-05-18 19:53:13 +02:00
// Save the results to disk
save ( ) ;
2016-05-26 22:03:12 +02:00
// Report the objects for which we were unable to compute an energy value for
if ( ConfigurationHandler . Settings . energyValueDebugLoggingEnabled ) {
uncomputedStacks . stream ( )
. filter ( wrappedStack - > getEnergyValue ( stackValueMap , wrappedStack , false ) = = null )
. forEach ( wrappedStack - > LogHelper . info ( ENERGY_VALUE_MARKER , " Unable to compute an energy value for {} " , wrappedStack ) ) ;
}
2015-02-20 04:09:10 +01:00
}
2016-05-18 19:53:13 +02:00
/ * *
*
* @param stackValueMap
* @return
* /
private Map < WrappedStack , EnergyValue > calculateStackValueMap ( Map < WrappedStack , EnergyValue > stackValueMap ) {
2015-02-12 06:15:45 +01:00
2016-05-18 19:53:13 +02:00
LogHelper . info ( ENERGY_VALUE_MARKER , " Beginning energy value calculation " ) ;
long startingTime = System . nanoTime ( ) ;
2015-02-12 06:15:45 +01:00
2016-05-18 19:53:13 +02:00
Map < WrappedStack , EnergyValue > computedMap = new TreeMap < > ( stackValueMap ) ;
Map < WrappedStack , EnergyValue > tempComputedMap = new TreeMap < > ( ) ;
int passNumber = 0 ;
2015-04-21 03:16:48 +02:00
2016-05-18 19:53:13 +02:00
while ( ( passNumber = = 0 | | tempComputedMap . size ( ) ! = computedMap . size ( ) ) & & passNumber < 16 ) {
2015-02-11 05:38:05 +01:00
2016-05-18 19:53:13 +02:00
long passStartTime = System . nanoTime ( ) ;
passNumber + + ;
computedMap . putAll ( tempComputedMap ) ;
2016-05-11 21:59:52 +02:00
2016-05-18 19:53:13 +02:00
tempComputedMap = new TreeMap < > ( computedMap ) ;
2016-05-20 19:56:53 +02:00
for ( WrappedStack recipeOutput : RecipeRegistry . INSTANCE . getRecipeMappings ( ) . keySet ( ) ) {
2016-05-11 21:59:52 +02:00
2016-05-27 22:03:14 +02:00
WrappedStack unitWrappedStack = WrappedStack . wrap ( recipeOutput , 1 ) ;
2016-05-18 19:53:13 +02:00
// We won't attempt to recalculate values that already have a pre-calculation value assignment
2016-05-27 22:03:14 +02:00
if ( ! stackValueMap . containsKey ( unitWrappedStack ) ) {
2016-05-20 19:56:53 +02:00
for ( Set < WrappedStack > recipeInputs : RecipeRegistry . INSTANCE . getRecipeMappings ( ) . get ( recipeOutput ) ) {
2015-11-19 21:24:40 +01:00
2016-05-27 22:03:14 +02:00
EnergyValue currentOutputValue = getEnergyValue ( tempComputedMap , unitWrappedStack , false ) ;
2016-05-18 19:53:13 +02:00
EnergyValue computedOutputValue = computeFromInputs ( tempComputedMap , recipeOutput , recipeInputs ) ;
2015-02-12 06:15:45 +01:00
2016-05-18 19:53:13 +02:00
if ( computedOutputValue ! = null & & computedOutputValue . compareTo ( currentOutputValue ) < 0 ) {
2015-05-02 20:07:01 +02:00
2016-05-27 22:03:14 +02:00
uncomputedStacks . remove ( unitWrappedStack ) ;
2015-05-02 20:07:01 +02:00
2016-05-18 19:53:13 +02:00
if ( ConfigurationHandler . Settings . energyValueDebugLoggingEnabled ) {
2016-05-27 22:03:14 +02:00
LogHelper . info ( ENERGY_VALUE_MARKER , " Pass {}: Calculated value {} for object {} with recipe inputs {} and output {} " , passNumber , computedOutputValue , unitWrappedStack , recipeInputs , recipeOutput ) ;
2016-05-18 19:53:13 +02:00
}
2016-05-11 21:59:52 +02:00
2016-05-27 22:03:14 +02:00
tempComputedMap . put ( unitWrappedStack , computedOutputValue ) ;
2016-05-18 19:53:13 +02:00
}
else if ( computedOutputValue ! = null ) {
2016-05-27 22:03:14 +02:00
uncomputedStacks . add ( unitWrappedStack ) ;
2016-05-18 19:53:13 +02:00
}
}
2015-05-03 01:23:35 +02:00
}
2015-03-23 13:12:44 +01:00
}
2015-02-12 06:15:45 +01:00
2016-05-18 19:53:13 +02:00
long passDuration = System . nanoTime ( ) - passStartTime ;
if ( ConfigurationHandler . Settings . energyValueDebugLoggingEnabled ) {
2016-05-26 22:03:12 +02:00
LogHelper . info ( ENERGY_VALUE_MARKER , " Pass {}: Calculated {} different values for objects in {} ms " , passNumber , tempComputedMap . size ( ) , passDuration / 100000 ) ;
2015-03-23 13:12:44 +01:00
}
2015-02-12 06:15:45 +01:00
}
2016-05-18 19:53:13 +02:00
long endingTime = System . nanoTime ( ) - startingTime ;
2016-05-26 22:03:12 +02:00
LogHelper . info ( ENERGY_VALUE_MARKER , " Finished energy value calculation - calculated {} new values for objects in {} ms " , computedMap . size ( ) - stackValueMap . size ( ) , endingTime / 100000 ) ;
2015-02-16 03:13:35 +01:00
2016-05-18 19:53:13 +02:00
return computedMap ;
2015-02-16 03:13:35 +01:00
}
2016-05-18 19:53:13 +02:00
private void calculateValueStackMap ( ) {
2015-11-19 21:24:40 +01:00
2016-05-20 19:56:53 +02:00
SortedMap < EnergyValue , Set < WrappedStack > > tempValueMap = new TreeMap < > ( ) ;
2015-02-16 03:13:35 +01:00
2016-05-18 19:53:13 +02:00
for ( WrappedStack wrappedStack : getEnergyValues ( ) . keySet ( ) ) {
2015-02-16 03:13:35 +01:00
2016-05-18 19:53:13 +02:00
if ( wrappedStack ! = null ) {
EnergyValue energyValue = getEnergyValues ( ) . get ( wrappedStack ) ;
if ( energyValue ! = null ) {
if ( tempValueMap . containsKey ( energyValue ) ) {
if ( ! ( tempValueMap . get ( energyValue ) . contains ( wrappedStack ) ) ) {
tempValueMap . get ( energyValue ) . add ( wrappedStack ) ;
}
}
else {
2016-05-20 19:56:53 +02:00
tempValueMap . put ( energyValue , new TreeSet < > ( Arrays . asList ( wrappedStack ) ) ) ;
2016-05-18 19:53:13 +02:00
}
2015-02-16 03:13:35 +01:00
}
}
2016-05-18 19:53:13 +02:00
}
valueStackMap = ImmutableSortedMap . copyOf ( tempValueMap ) ;
}
2015-02-16 03:13:35 +01:00
2016-05-27 22:03:14 +02:00
private static Set < ItemStack > filterForItemStacks ( Set < WrappedStack > wrappedStacks ) {
Set < ItemStack > itemStacks = new TreeSet < > ( Comparators . ID_COMPARATOR ) ;
for ( WrappedStack wrappedStack : wrappedStacks ) {
if ( wrappedStack . getWrappedObject ( ) instanceof ItemStack ) {
itemStacks . add ( ( ItemStack ) wrappedStack . getWrappedObject ( ) ) ;
}
else if ( wrappedStack . getWrappedObject ( ) instanceof OreStack ) {
itemStacks . addAll ( OreDictionary . getOres ( ( ( OreStack ) wrappedStack . getWrappedObject ( ) ) . oreName ) ) ;
}
}
return itemStacks ;
}
2016-05-18 19:53:13 +02:00
/ * *
* Saves the pre - calculation , post - calculation , and calculated energy value maps to disk
* /
public void save ( ) {
2015-02-16 03:13:35 +01:00
2016-05-18 19:53:13 +02:00
/ * *
* If the current values were synched to us from a server , do not save them to disk as they would override
* the local ones
* /
2016-05-25 05:12:49 +02:00
if ( shouldSave ) {
if ( valuesNeedRegeneration ) {
if ( energyValuesFile . exists ( ) ) {
energyValuesFile . delete ( ) ;
}
}
else {
SerializationHelper . writeMapToFile ( stackValueMap , energyValuesFile ) ;
}
2016-05-18 19:53:13 +02:00
}
2016-05-19 02:54:04 +02:00
SerializationHelper . writeMapToFile ( preCalculationStackValueMap , preCalculationValuesFile ) ;
SerializationHelper . writeMapToFile ( postCalculationStackValueMap , postCalculationValuesFile ) ;
2016-05-18 19:53:13 +02:00
}
/ * *
* Loads the pre - calculation , post - calculation , and calculated energy value maps from disk . In the event that either
* the pre / post calculation maps can not be loaded from disk they will be initialized as empty maps . If the
* calculated energy value map can not be loaded from disk then the values will be computed from the pre / post
* calculation maps
* /
public void load ( ) {
2016-05-25 19:25:52 +02:00
// Load in pre calculation value assignments from file
Map < WrappedStack , EnergyValue > fileValueMap = null ;
2016-05-18 19:53:13 +02:00
try {
2016-05-25 19:25:52 +02:00
fileValueMap = SerializationHelper . readMapFromFile ( preCalculationValuesFile ) ;
}
catch ( FileNotFoundException e ) {
LogHelper . warn ( ENERGY_VALUE_MARKER , " No pre calculation energy values were loaded from file - could not find {} " , preCalculationValuesFile . getAbsolutePath ( ) ) ;
}
if ( fileValueMap ! = null ) {
for ( WrappedStack wrappedStack : fileValueMap . keySet ( ) ) {
if ( wrappedStack ! = null & & wrappedStack . getWrappedObject ( ) ! = null & & fileValueMap . get ( wrappedStack ) ! = null ) {
preCalculationStackValueMap . put ( wrappedStack , fileValueMap . get ( wrappedStack ) ) ;
}
}
2015-02-16 03:13:35 +01:00
}
2016-05-25 19:25:52 +02:00
// Load in post calculation value assignments from file
fileValueMap = null ;
2016-05-18 19:53:13 +02:00
try {
2016-05-25 19:25:52 +02:00
fileValueMap = SerializationHelper . readMapFromFile ( postCalculationValuesFile ) ;
}
catch ( FileNotFoundException e ) {
LogHelper . warn ( ENERGY_VALUE_MARKER , " No post calculation energy values were loaded from file - could not find {} " , postCalculationValuesFile . getAbsolutePath ( ) ) ;
}
if ( fileValueMap ! = null ) {
for ( WrappedStack wrappedStack : fileValueMap . keySet ( ) ) {
if ( wrappedStack ! = null & & wrappedStack . getWrappedObject ( ) ! = null & & fileValueMap . get ( wrappedStack ) ! = null ) {
postCalculationStackValueMap . put ( wrappedStack , fileValueMap . get ( wrappedStack ) ) ;
}
}
2016-05-18 19:53:13 +02:00
}
2016-05-25 19:25:52 +02:00
// Load the calculated energy values assignments from file
fileValueMap = null ;
2016-05-18 19:53:13 +02:00
try {
2016-05-25 19:25:52 +02:00
fileValueMap = SerializationHelper . readMapFromFile ( energyValuesFile ) ;
}
catch ( FileNotFoundException e ) {
LogHelper . warn ( " No calculated energy values were loaded from file - could not find {} " , energyValuesFile . getAbsolutePath ( ) ) ;
LogHelper . info ( " Recomputing energy values " , energyValuesFile . getAbsolutePath ( ) ) ;
compute ( ) ;
}
if ( fileValueMap ! = null ) {
2016-05-18 19:53:13 +02:00
ImmutableSortedMap . Builder < WrappedStack , EnergyValue > stackMapBuilder = ImmutableSortedMap . naturalOrder ( ) ;
2016-05-25 19:25:52 +02:00
for ( WrappedStack wrappedStack : fileValueMap . keySet ( ) ) {
if ( wrappedStack ! = null & & wrappedStack . getWrappedObject ( ) ! = null & & fileValueMap . get ( wrappedStack ) ! = null ) {
stackMapBuilder . put ( wrappedStack , fileValueMap . get ( wrappedStack ) ) ;
}
}
2016-05-18 19:53:13 +02:00
stackValueMap = stackMapBuilder . build ( ) ;
calculateValueStackMap ( ) ;
}
2015-02-16 03:13:35 +01:00
}
2016-05-18 19:53:13 +02:00
/ * *
*
*
* @param valueMap
* /
public void load ( Map < WrappedStack , EnergyValue > valueMap ) {
2015-11-19 21:24:40 +01:00
2016-05-25 05:12:49 +02:00
if ( valueMap ! = null ) {
2015-02-16 03:13:35 +01:00
2016-05-25 05:12:49 +02:00
setShouldSave ( false ) ;
2016-05-18 19:53:13 +02:00
ImmutableSortedMap . Builder < WrappedStack , EnergyValue > stackMappingsBuilder = ImmutableSortedMap . naturalOrder ( ) ;
2016-05-25 19:25:52 +02:00
valueMap . keySet ( ) . stream ( )
. filter ( wrappedStack - > wrappedStack ! = null & & wrappedStack . getWrappedObject ( ) ! = null & & valueMap . get ( wrappedStack ) ! = null )
. forEach ( wrappedStack - > stackMappingsBuilder . put ( wrappedStack , valueMap . get ( wrappedStack ) ) ) ;
2016-05-18 19:53:13 +02:00
stackValueMap = stackMappingsBuilder . build ( ) ;
calculateValueStackMap ( ) ;
2015-02-16 03:13:35 +01:00
}
}
2014-06-14 21:40:45 +02:00
}