diff options
author | Martin Robertz <dream-master@gmx.net> | 2021-10-30 13:06:47 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-30 13:06:47 +0200 |
commit | cee84d9882ae4f988891856eba8c31ebd383e7ff (patch) | |
tree | bfde18f6d875e23ca0e4ecff3be3d04d1e87abfc /src/main/java/gregtech/api/util | |
parent | f798f8a8a6fb3ca13d35928d49525d384b6302cc (diff) | |
parent | 64b07bba3aad35118bda5289aecc85cdccffbc27 (diff) | |
download | GT5-Unofficial-cee84d9882ae4f988891856eba8c31ebd383e7ff.tar.gz GT5-Unofficial-cee84d9882ae4f988891856eba8c31ebd383e7ff.tar.bz2 GT5-Unofficial-cee84d9882ae4f988891856eba8c31ebd383e7ff.zip |
Merge branch 'experimental' into Boxinator
Diffstat (limited to 'src/main/java/gregtech/api/util')
-rw-r--r-- | src/main/java/gregtech/api/util/GT_OreDictUnificator.java | 37 | ||||
-rw-r--r-- | src/main/java/gregtech/api/util/GT_Recipe.java | 30 | ||||
-rw-r--r-- | src/main/java/gregtech/api/util/GT_Utility.java | 76 |
3 files changed, 120 insertions, 23 deletions
diff --git a/src/main/java/gregtech/api/util/GT_OreDictUnificator.java b/src/main/java/gregtech/api/util/GT_OreDictUnificator.java index 54ef5b2866..a017cf3bb0 100644 --- a/src/main/java/gregtech/api/util/GT_OreDictUnificator.java +++ b/src/main/java/gregtech/api/util/GT_OreDictUnificator.java @@ -223,26 +223,30 @@ public class GT_OreDictUnificator { rStack = tPrefixMaterial.mUnificationTarget; if (GT_Utility.isStackInvalid(rStack)) return !alreadyCompared && GT_Utility.areStacksEqual(aStack, unified_tStack, true); - assert rStack != null; rStack.setTagCompound(aStack.getTagCompound()); return GT_Utility.areStacksEqual(rStack, unified_tStack, true); } public static List<ItemStack> getNonUnifiedStacks(Object obj) { - synchronized (sUnificationTable) { - if (sUnificationTable.isEmpty() && !sItemStack2DataMap.isEmpty()) { - for (GT_ItemStack tGTStack0 : sItemStack2DataMap.keySet()) { - ItemStack tStack0 = tGTStack0.toStack(); - ItemStack tStack1 = get(false, tStack0); - if (!GT_Utility.areStacksEqual(tStack0, tStack1)) { - GT_ItemStack tGTStack1 = new GT_ItemStack(tStack1); - List<ItemStack> list = sUnificationTable.computeIfAbsent(tGTStack1, k -> new ArrayList<>()); - if (!list.contains(tStack0)) - list.add(tStack0); - } - } - } - } + if (sUnificationTable.isEmpty() && !sItemStack2DataMap.isEmpty()) { + // use something akin to double check lock. this synchronization overhead is causing lag whenever my + // 5900x tries to do NEI lookup + synchronized (sUnificationTable) { + if (sUnificationTable.isEmpty() && !sItemStack2DataMap.isEmpty()) { + for (GT_ItemStack tGTStack0 : sItemStack2DataMap.keySet()) { + ItemStack tStack0 = tGTStack0.toStack(); + ItemStack tStack1 = get_nocopy(false, tStack0); + if (!GT_Utility.areStacksEqual(tStack0, tStack1)) { + GT_ItemStack tGTStack1 = new GT_ItemStack(tStack1); + List<ItemStack> list = sUnificationTable.computeIfAbsent(tGTStack1, k -> new ArrayList<>()); + // greg's original code tries to dedupe the list using List#contains, which won't work + // on vanilla ItemStack. I removed it since it never worked and can be slow. + list.add(tStack0); + } + } + } + } + } ItemStack[] aStacks = {}; if (obj instanceof ItemStack) aStacks = new ItemStack[]{(ItemStack) obj}; @@ -257,7 +261,6 @@ public class GT_OreDictUnificator { if (tList != null) { for (ItemStack tStack : tList) { ItemStack tStack1 = GT_Utility.copyAmount(aStack.stackSize, tStack); - tStack1.setTagCompound(aStack.getTagCompound()); rList.add(tStack1); } } @@ -315,7 +318,7 @@ public class GT_OreDictUnificator { public static ItemData getItemData(ItemStack aStack) { if (GT_Utility.isStackInvalid(aStack)) return null; ItemData rData = sItemStack2DataMap.get(new GT_ItemStack(aStack)); - if (rData == null) rData = sItemStack2DataMap.get(new GT_ItemStack(GT_Utility.copyMetaData(W, aStack))); + if (rData == null) rData = sItemStack2DataMap.get(new GT_ItemStack(aStack, true)); return rData; } diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java index f941a86f5c..96018571e9 100644 --- a/src/main/java/gregtech/api/util/GT_Recipe.java +++ b/src/main/java/gregtech/api/util/GT_Recipe.java @@ -302,6 +302,13 @@ public class GT_Recipe implements Comparable<GT_Recipe> { } } + public GT_Recipe(FluidStack aInput1, FluidStack aOutput1, int aDuration, int aEUt) { + this(false, null, null, null, null, new FluidStack[]{aInput1}, new FluidStack[]{aOutput1}, Math.max(aDuration, 1), aEUt, 0); + if (mFluidInputs.length > 0 && mFluidOutputs[0] != null) { + GT_Recipe_Map.sVacuumRecipes.addRecipe(this); + } + } + //Dummy GT_Recipe maker... public GT_Recipe(ItemStack[] aInputs, ItemStack[] aOutputs, Object aSpecialItems, int[] aChances, FluidStack[] aFluidInputs, FluidStack[] aFluidOutputs, int aDuration, int aEUt, int aSpecialValue){ this(true, aInputs, aOutputs, aSpecialItems, aChances, aFluidInputs, aFluidOutputs, aDuration, aEUt, aSpecialValue); @@ -565,6 +572,10 @@ public class GT_Recipe implements Comparable<GT_Recipe> { * Contains all Recipe Maps */ public static final Collection<GT_Recipe_Map> sMappings = new ArrayList<>(); + /** + * All recipe maps indexed by their {@link #mUniqueIdentifier}. + */ + public static final Map<String, GT_Recipe_Map> sIndexedMappings = new HashMap<>(); public static final GT_Recipe_Map sOreWasherRecipes = new GT_Recipe_Map(new HashSet<>(500), "gt.recipe.orewasher", "Ore Washing Plant", null, RES_PATH_GUI + "basicmachines/OreWasher", 1, 3, 1, 1, 1, E, 1, E, true, true); public static final GT_Recipe_Map sThermalCentrifugeRecipes = new GT_Recipe_Map(new HashSet<>(1000), "gt.recipe.thermalcentrifuge", "Thermal Centrifuge", null, RES_PATH_GUI + "basicmachines/ThermalCentrifuge", 1, 3, 1, 0, 2, E, 1, E, true, true); @@ -589,7 +600,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> { public static final GT_Recipe_Map sPressRecipes = new GT_Recipe_Map_FormingPress(new HashSet<>(300), "gt.recipe.press", "Forming Press", null, RES_PATH_GUI + "basicmachines/Press", 2, 1, 2, 0, 1, E, 1, E, true, true); public static final GT_Recipe_Map sLaserEngraverRecipes = new GT_Recipe_Map(new HashSet<>(810), "gt.recipe.laserengraver", "Precision Laser Engraver", null, RES_PATH_GUI + "basicmachines/LaserEngraver", 2, 1, 2, 0, 1, E, 1, E, true, true); public static final GT_Recipe_Map sMixerRecipes = new GT_Recipe_Map(new HashSet<>(900), "gt.recipe.mixer", "Mixer", null, RES_PATH_GUI + "basicmachines/Mixer2", 9, 1, 1, 0, 1, E, 1, E, true, true); - public static final GT_Recipe_Map sAutoclaveRecipes = new GT_Recipe_Map(new HashSet<>(300), "gt.recipe.autoclave", "Autoclave", null, RES_PATH_GUI + "basicmachines/Autoclave", 2, 1, 1, 1, 1, E, 1, E, true, true); + public static final GT_Recipe_Map sAutoclaveRecipes = new GT_Recipe_Map(new HashSet<>(300), "gt.recipe.autoclave", "Autoclave", null, RES_PATH_GUI + "basicmachines/Autoclave4", 2, 4, 1, 1, 1, E, 1, E, true, true); public static final GT_Recipe_Map sElectroMagneticSeparatorRecipes = new GT_Recipe_Map(new HashSet<>(50), "gt.recipe.electromagneticseparator", "Electromagnetic Separator", null, RES_PATH_GUI + "basicmachines/ElectromagneticSeparator", 1, 3, 1, 0, 1, E, 1, E, true, true); public static final GT_Recipe_Map sPolarizerRecipes = new GT_Recipe_Map(new HashSet<>(300), "gt.recipe.polarizer", "Electromagnetic Polarizer", null, RES_PATH_GUI + "basicmachines/Polarizer", 1, 1, 1, 0, 1, E, 1, E, true, true); public static final GT_Recipe_Map sMaceratorRecipes = new GT_Recipe_Map_Macerator(new HashSet<>(16600), "gt.recipe.macerator", "Pulverization", null, RES_PATH_GUI + "basicmachines/Macerator4", 1, 4, 1, 0, 1, E, 1, E, true, true); @@ -609,7 +620,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> { public static final GT_Recipe_Map sBlastRecipes = new GT_Recipe_Map(new HashSet<>(800), "gt.recipe.blastfurnace", "Blast Furnace", null, RES_PATH_GUI + "basicmachines/Default", 2, 2, 1, 0, 1, "Heat Capacity: ", 1, " K", false, true); public static final GT_Recipe_Map sPrimitiveBlastRecipes = new GT_Recipe_Map(new HashSet<>(200), "gt.recipe.primitiveblastfurnace", "Primitive Blast Furnace", null, RES_PATH_GUI + "basicmachines/Default", 3, 3, 1, 0, 1, E, 1, E, false, true); public static final GT_Recipe_Map sImplosionRecipes = new GT_Recipe_Map(new HashSet<>(900), "gt.recipe.implosioncompressor", "Implosion Compressor", null, RES_PATH_GUI + "basicmachines/Default", 2, 2, 2, 0, 1, E, 1, E, true, true); - public static final GT_Recipe_Map sVacuumRecipes = new GT_Recipe_Map(new HashSet<>(305), "gt.recipe.vacuumfreezer", "Vacuum Freezer", null, RES_PATH_GUI + "basicmachines/Default", 1, 1, 1, 0, 1, E, 1, E, false, true); + public static final GT_Recipe_Map sVacuumRecipes = new GT_Recipe_Map(new HashSet<>(305), "gt.recipe.vacuumfreezer", "Vacuum Freezer", null, RES_PATH_GUI + "basicmachines/Default", 1, 1, 0, 0, 1, E, 1, E, false, true); public static final GT_Recipe_Map sChemicalRecipes = new GT_Recipe_Map(new HashSet<>(1170), "gt.recipe.chemicalreactor", "Chemical Reactor", null, RES_PATH_GUI + "basicmachines/ChemicalReactor", 2, 2, 1, 0, 1, E, 1, E, true, true); public static final GT_Recipe_Map sMultiblockChemicalRecipes = new GT_Recipe_Map_LargeChemicalReactor(); public static final GT_Recipe_Map sDistillationRecipes = new GT_Recipe_Map_DistillationTower(); @@ -646,7 +657,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> { public static final GT_Recipe_Map_Fuel sHugeNaquadahReactorFuels = new GT_Recipe_Map_Fuel(new HashSet<>(1), "gt.recipe.fluidnaquadahreactor", "Naquadah Reactor MkIII", null, RES_PATH_GUI + "basicmachines/Default", 1, 1, 0, 0, 1, "Fuel Value: ", 1000, " EU", true, true); public static final GT_Recipe_Map_Fuel sExtremeNaquadahReactorFuels = new GT_Recipe_Map_Fuel(new HashSet<>(1), "gt.recipe.hugenaquadahreactor", "Naquadah Reactor MkIV", null, RES_PATH_GUI + "basicmachines/Default", 1, 1, 0, 0, 1, "Fuel Value: ", 1000, " EU", true, true); public static final GT_Recipe_Map_Fuel sUltraHugeNaquadahReactorFuels = new GT_Recipe_Map_Fuel(new HashSet<>(1), "gt.recipe.extrahugenaquadahreactor", "Naquadah Reactor MkV", null, RES_PATH_GUI + "basicmachines/Default", 1, 1, 0, 0, 1, "Fuel Value: ", 1000, " EU", true, true); - public static final GT_Recipe_Map_Fuel sFluidNaquadahReactorFuels = new GT_Recipe_Map_Fuel(new HashSet<>(1), "gt.recipe.fluidnaquadahreactor", "Fluid Naquadah Reactor", null, RES_PATH_GUI + "basicmachines/Default", 1, 1, 0, 0, 1, "Fuel Value: ", 1000, " EU", true, true); + public static final GT_Recipe_Map_Fuel sFluidNaquadahReactorFuels = new GT_Recipe_Map_Fuel(new HashSet<>(1), "gt.recipe.fluidfuelnaquadahreactor", "Fluid Naquadah Reactor", null, RES_PATH_GUI + "basicmachines/Default", 1, 1, 0, 0, 1, "Fuel Value: ", 1000, " EU", true, true); public static final GT_Recipe_Map_LargeBoilerFakeFuels sLargeBoilerFakeFuels = new GT_Recipe_Map_LargeBoilerFakeFuels(); /** @@ -679,6 +690,12 @@ public class GT_Recipe implements Comparable<GT_Recipe> { public final boolean mNEIAllowed, mShowVoltageAmperageInNEI; /** + * Unique identifier for this recipe map. Generated from aUnlocalizedName and a few other parameters. + * See constructor for details. + */ + public final String mUniqueIdentifier; + + /** * Initialises a new type of Recipe Handler. * * @param aRecipeList a List you specify as Recipe List. Usually just an ArrayList with a pre-initialised Size. @@ -710,6 +727,9 @@ public class GT_Recipe implements Comparable<GT_Recipe> { GregTech_API.sFluidMappings.add(mRecipeFluidMap); GregTech_API.sItemStackMappings.add(mRecipeItemMap); GT_LanguageManager.addStringLocalization(mUnlocalizedName = aUnlocalizedName, aLocalName); + mUniqueIdentifier = String.format("%s_%d_%d_%d_%d_%d", aUnlocalizedName, aAmperage, aUsualInputCount, aUsualOutputCount, aMinimalInputFluids, aMinimalInputItems); + if (sIndexedMappings.put(mUniqueIdentifier, this) != null) + throw new IllegalArgumentException("Duplicate recipe map registered: " + mUniqueIdentifier); } public GT_Recipe addRecipe(boolean aOptimize, ItemStack[] aInputs, ItemStack[] aOutputs, Object aSpecial, int[] aOutputChances, FluidStack[] aFluidInputs, FluidStack[] aFluidOutputs, int aDuration, int aEUt, int aSpecialValue) { @@ -793,7 +813,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> { * @return if this Item is a valid Input for any for the Recipes */ public boolean containsInput(ItemStack aStack) { - return aStack != null && (mRecipeItemMap.containsKey(new GT_ItemStack(aStack)) || mRecipeItemMap.containsKey(new GT_ItemStack(GT_Utility.copyMetaData(W, aStack)))); + return aStack != null && (mRecipeItemMap.containsKey(new GT_ItemStack(aStack)) || mRecipeItemMap.containsKey(new GT_ItemStack(aStack, true))); } /** @@ -879,7 +899,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> { if (tRecipes != null) for (GT_Recipe tRecipe : tRecipes) if (!tRecipe.mFakeRecipe && tRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs)) return tRecipe.mEnabled && aVoltage * mAmperage >= tRecipe.mEUt ? tRecipe : null; - tRecipes = mRecipeItemMap.get(new GT_ItemStack(GT_Utility.copyMetaData(W, tStack))); + tRecipes = mRecipeItemMap.get(new GT_ItemStack(tStack, true)); if (tRecipes != null) for (GT_Recipe tRecipe : tRecipes) if (!tRecipe.mFakeRecipe && tRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs)) return tRecipe.mEnabled && aVoltage * mAmperage >= tRecipe.mEUt ? tRecipe : null; diff --git a/src/main/java/gregtech/api/util/GT_Utility.java b/src/main/java/gregtech/api/util/GT_Utility.java index be5f978d6e..b3f3c6d666 100644 --- a/src/main/java/gregtech/api/util/GT_Utility.java +++ b/src/main/java/gregtech/api/util/GT_Utility.java @@ -1,6 +1,7 @@ package gregtech.api.util; import cofh.api.transport.IItemDuct; +import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.gtnewhorizon.structurelib.alignment.IAlignment; @@ -28,6 +29,7 @@ import gregtech.api.objects.ItemData; import gregtech.api.threads.GT_Runnable_Sound; import gregtech.api.util.extensions.ArrayExt; import gregtech.common.GT_Proxy; +import gregtech.common.blocks.GT_Block_Ores_Abstract; import ic2.api.recipe.IRecipeInput; import ic2.api.recipe.RecipeInputItemStack; import ic2.api.recipe.RecipeInputOreDict; @@ -80,7 +82,9 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.*; import java.util.Map.Entry; +import java.util.function.Function; import java.util.function.IntFunction; +import java.util.function.Supplier; import static gregtech.GT_Mod.GT_FML_LOGGER; import static gregtech.api.enums.GT_Values.*; @@ -102,6 +106,9 @@ public class GT_Utility { private static final List<FluidContainerData> sFluidContainerList = new ArrayList<>(); private static final Map<GT_ItemStack, FluidContainerData> sFilledContainerToData = new /*Concurrent*/HashMap<>(); private static final Map<GT_ItemStack, Map<Fluid, FluidContainerData>> sEmptyContainerToFluidToData = new /*Concurrent*/HashMap<>(); + private static final Map<Fluid, List<ItemStack>> sFluidToContainers = new HashMap<>(); + /** Must use {@code Supplier} here because the ore prefixes have not yet been registered at class load time. */ + private static final Map<OrePrefixes, Supplier<ItemStack>> sOreToCobble = new HashMap<>(); public static volatile int VERSION = 509; public static boolean TE_CHECK = false, BC_CHECK = false, CHECK_ALL = true, RF_CHECK = false; public static Map<GT_PlayedSound, Integer> sPlayedSoundMap = new /*Concurrent*/HashMap<>(); @@ -116,6 +123,29 @@ public class GT_Utility { GregTech_API.sItemStackMappings.add(sFilledContainerToData); GregTech_API.sItemStackMappings.add(sEmptyContainerToFluidToData); + + // 1 is the magic index to get the cobblestone block. + // See: GT_Block_Stones.java, GT_Block_Granites.java + Function<Materials, Supplier<ItemStack>> materialToCobble = + m -> Suppliers.memoize(() -> GT_OreDictUnificator.getOres(OrePrefixes.stone, m).get(1))::get; + sOreToCobble.put( + OrePrefixes.oreBlackgranite, + materialToCobble.apply(Materials.GraniteBlack)); + sOreToCobble.put( + OrePrefixes.oreRedgranite, + materialToCobble.apply(Materials.GraniteRed)); + sOreToCobble.put( + OrePrefixes.oreMarble, + materialToCobble.apply(Materials.Marble)); + sOreToCobble.put( + OrePrefixes.oreBasalt, + materialToCobble.apply(Materials.Basalt)); + sOreToCobble.put( + OrePrefixes.oreNetherrack, + () -> new ItemStack(Blocks.netherrack)); + sOreToCobble.put( + OrePrefixes.oreEndstone, + () -> new ItemStack(Blocks.end_stone)); } public static int safeInt(long number, int margin){ @@ -918,14 +948,22 @@ public class GT_Utility { public static void reInit() { sFilledContainerToData.clear(); sEmptyContainerToFluidToData.clear(); + sFluidToContainers.clear(); for (FluidContainerData tData : sFluidContainerList) { sFilledContainerToData.put(new GT_ItemStack(tData.filledContainer), tData); Map<Fluid, FluidContainerData> tFluidToContainer = sEmptyContainerToFluidToData.get(new GT_ItemStack(tData.emptyContainer)); + List<ItemStack> tContainers = sFluidToContainers.get(tData.fluid.getFluid()); if (tFluidToContainer == null) { sEmptyContainerToFluidToData.put(new GT_ItemStack(tData.emptyContainer), tFluidToContainer = new /*Concurrent*/HashMap<>()); GregTech_API.sFluidMappings.add(tFluidToContainer); } tFluidToContainer.put(tData.fluid.getFluid(), tData); + if (tContainers == null) { + tContainers = new ArrayList<>(); + tContainers.add(tData.filledContainer); + sFluidToContainers.put(tData.fluid.getFluid(), tContainers); + } + else tContainers.add(tData.filledContainer); } } @@ -933,11 +971,27 @@ public class GT_Utility { sFluidContainerList.add(aData); sFilledContainerToData.put(new GT_ItemStack(aData.filledContainer), aData); Map<Fluid, FluidContainerData> tFluidToContainer = sEmptyContainerToFluidToData.get(new GT_ItemStack(aData.emptyContainer)); + List<ItemStack> tContainers = sFluidToContainers.get(aData.fluid.getFluid()); if (tFluidToContainer == null) { sEmptyContainerToFluidToData.put(new GT_ItemStack(aData.emptyContainer), tFluidToContainer = new /*Concurrent*/HashMap<>()); GregTech_API.sFluidMappings.add(tFluidToContainer); } tFluidToContainer.put(aData.fluid.getFluid(), aData); + if (tContainers == null) { + tContainers = new ArrayList<>(); + tContainers.add(aData.filledContainer); + sFluidToContainers.put(aData.fluid.getFluid(), tContainers); + } + else tContainers.add(aData.filledContainer); + } + + public static List<ItemStack> getContainersFromFluid(FluidStack tFluidStack) { + if (tFluidStack != null) { + List<ItemStack> tContainers = sFluidToContainers.get(tFluidStack.getFluid()); + if (tContainers == null) return new ArrayList<>(); + return tContainers; + } + return new ArrayList<>(); } public static ItemStack fillFluidContainer(FluidStack aFluid, ItemStack aStack, boolean aRemoveFluidDirectly, boolean aCheckIFluidContainerItems) { @@ -2708,7 +2762,9 @@ public class GT_Utility { ); public static boolean isOre(Block aBlock, int aMeta) { - return isOre(new ItemStack(aBlock, 1, aMeta)) || ORE_BLOCK_CLASSES.contains(aBlock.getClass().getName()); + return (aBlock instanceof GT_Block_Ores_Abstract) + || isOre(new ItemStack(aBlock, 1, aMeta)) + || ORE_BLOCK_CLASSES.contains(aBlock.getClass().getName()); } public static boolean isOre(ItemStack aStack) { @@ -2719,6 +2775,24 @@ public class GT_Utility { return false; } + /** + * Do <b>NOT</b> mutate the returned {@code ItemStack}! + * We return {@code ItemStack} instead of {@code Block} so that we can include metadata. + */ + public static ItemStack getCobbleForOre(Block ore, short metaData) { + // We need to convert small ores to regular ores because small ores don't have associated ItemData. + // We take the modulus of the metadata by 16000 because that is the magic number to convert small ores to regular ores. + // See: GT_TileEntity_Ores.java + ItemData association = GT_OreDictUnificator.getAssociation(new ItemStack(Item.getItemFromBlock(ore), 1, metaData % 16000)); + if (association != null) { + Supplier<ItemStack> supplier = sOreToCobble.get(association.mPrefix); + if (supplier != null) { + return supplier.get(); + } + } + return new ItemStack(Blocks.cobblestone); + } + public static Optional<GT_Recipe> reverseShapelessRecipe(ItemStack output, Object... aRecipe) { if (output == null) { return Optional.empty(); |