diff options
Diffstat (limited to 'src/main/java/bartworks/system/material/CircuitGeneration')
5 files changed, 1060 insertions, 0 deletions
diff --git a/src/main/java/bartworks/system/material/CircuitGeneration/BWCircuitsLoader.java b/src/main/java/bartworks/system/material/CircuitGeneration/BWCircuitsLoader.java new file mode 100644 index 0000000000..55b42a662d --- /dev/null +++ b/src/main/java/bartworks/system/material/CircuitGeneration/BWCircuitsLoader.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2020 bartimaeusnek Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package bartworks.system.material.CircuitGeneration; + +public class BWCircuitsLoader { + + private static final BWMetaItems NEW_CIRCUITS = new BWMetaItems(); + + private BWCircuitsLoader() {} + + public static void initNewCircuits() { + + } +} diff --git a/src/main/java/bartworks/system/material/CircuitGeneration/BWMetaItems.java b/src/main/java/bartworks/system/material/CircuitGeneration/BWMetaItems.java new file mode 100644 index 0000000000..bafecfa0cd --- /dev/null +++ b/src/main/java/bartworks/system/material/CircuitGeneration/BWMetaItems.java @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2018-2020 bartimaeusnek Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package bartworks.system.material.CircuitGeneration; + +import static gregtech.api.recipe.RecipeMaps.formingPressRecipes; +import static gregtech.api.util.GTRecipeBuilder.SECONDS; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; + +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.IIcon; +import net.minecraftforge.fluids.FluidStack; + +import bartworks.MainMod; +import bartworks.common.loaders.ItemRegistry; +import bartworks.system.material.WerkstoffLoader; +import bartworks.util.BWUtil; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.GregTechAPI; +import gregtech.api.enums.GTValues; +import gregtech.api.enums.Materials; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.enums.SubTag; +import gregtech.api.enums.TCAspects; +import gregtech.api.enums.TierEU; +import gregtech.api.interfaces.IItemBehaviour; +import gregtech.api.interfaces.IItemContainer; +import gregtech.api.items.MetaBaseItem; +import gregtech.api.objects.ItemData; +import gregtech.api.recipe.RecipeMaps; +import gregtech.api.util.GTLanguageManager; +import gregtech.api.util.GTOreDictUnificator; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.GTUtility; + +public class BWMetaItems { + + public static BWMetaItems.BW_GT_MetaGenCircuits getCircuitParts() { + return BWMetaItems.NEW_CIRCUIT_PARTS; + } + + private static final BWMetaItems.BW_GT_MetaGenCircuits NEW_CIRCUIT_PARTS = new BWMetaItems.BW_GT_MetaGenCircuits(); + + static { + BWMetaItems.NEW_CIRCUIT_PARTS.addItem(0, "Circuit Imprint", "", SubTag.NO_UNIFICATION, SubTag.NO_RECYCLING); + BWMetaItems.NEW_CIRCUIT_PARTS.addItem(1, "Sliced Circuit", "", SubTag.NO_UNIFICATION, SubTag.NO_RECYCLING); + BWMetaItems.NEW_CIRCUIT_PARTS + .addItem(2, "Raw Imprint supporting Board", "A Raw Board needed for Circuit Imprints"); + BWMetaItems.NEW_CIRCUIT_PARTS.addItem(3, "Imprint supporting Board", "A Board needed for Circuit Imprints"); + + GTValues.RA.stdBuilder() + .itemInputs( + WerkstoffLoader.MagnetoResonaticDust.get(OrePrefixes.dust, 1), + WerkstoffLoader.ArInGaPhoBiBoTe.get(OrePrefixes.dust, 4)) + .itemOutputs(BWMetaItems.NEW_CIRCUIT_PARTS.getStack(2)) + .duration(15 * SECONDS) + .eut(TierEU.RECIPE_HV) + .addTo(formingPressRecipes); + + RecipeMaps.autoclaveRecipes.add( + new GTRecipe( + false, + new ItemStack[] { BWMetaItems.NEW_CIRCUIT_PARTS.getStack(2) }, + new ItemStack[] { BWMetaItems.NEW_CIRCUIT_PARTS.getStack(3) }, + null, + new int[] { 7500 }, + new FluidStack[] { Materials.SolderingAlloy.getMolten(576) }, + null, + 300, + (int) TierEU.RECIPE_EV, + BWUtil.CLEANROOM)); + } + + public static class BW_GT_MetaGenCircuits extends BWMetaItems.BW_GT_MetaGen_Item_Hook { + + public BW_GT_MetaGenCircuits() { + super("bwMetaGeneratedItem0"); + } + + public final ItemStack getStack(int meta) { + return getStack(meta, 1); + } + + public final ItemStack getStack(int meta, int stackSize) { + return new ItemStack(this, stackSize, meta); + } + + public final ItemStack getStackWithNBT(NBTTagCompound tag, int meta, int stackSize) { + ItemStack itemStack = getStack(meta, stackSize); + itemStack.setTagCompound(tag); + return itemStack; + } + + @Override + public void getSubItems(Item var1, CreativeTabs aCreativeTab, List<ItemStack> aList) { + if (aCreativeTab == this.getCreativeTab()) + for (NBTTagCompound tag : CircuitImprintLoader.recipeTagMap.keySet()) { + ItemStack stack = new ItemStack(BWMetaItems.NEW_CIRCUIT_PARTS, 1, 0); + stack.setTagCompound(tag); + aList.add(stack); + } + super.getSubItems(var1, aCreativeTab, aList); + } + + @Override + @SideOnly(Side.CLIENT) + public final void registerIcons(IIconRegister aIconRegister) { + + for (short i = 0; i < CircuitImprintLoader.reverseIDs; ++i) { + if (this.mEnabledItems.get(i)) { + BWUtil.set2DCoordTo1DArray( + i, + 0, + 2, + aIconRegister.registerIcon("gregtech:" + this.getUnlocalizedName() + "/" + i), + this.mIconList); + } + } + + for (short i = CircuitImprintLoader.reverseIDs; i < Short.MAX_VALUE; i++) { + if (this.mEnabledItems.get(i)) { + BWUtil.set2DCoordTo1DArray( + i, + 0, + 2, + Objects.requireNonNull(CircuitImprintLoader.circuitIIconRefs.get(i)) + .get(1) + .getIconIndex(), + this.mIconList); + BWUtil.set2DCoordTo1DArray( + i, + 1, + 2, + aIconRegister.registerIcon(MainMod.MOD_ID + ":WrapOverlay"), + this.mIconList); + } + } + } + + @Override + protected void addAdditionalToolTips(List<String> aList, ItemStack aStack, EntityPlayer aPlayer) { + if (aStack.getTagCompound() != null) { + ItemStack tagStack = CircuitImprintLoader.getStackFromTag(aStack.getTagCompound()); + String itemName = tagStack != null + ? GTLanguageManager.getTranslation(GTLanguageManager.getTranslateableItemStackName(tagStack)) + : "a circuit"; + + if (aStack.getItemDamage() == 0) { + aList.add("An imprint for: " + itemName); + } else if (aStack.getItemDamage() == 1) { + aList.add("A sliced " + itemName); + } + } else { + if (aStack.getItemDamage() == 0) { + aList.add("An imprint for a Circuit"); + } else if (aStack.getItemDamage() == 1) { + aList.add("A sliced Circuit"); + } + } + + super.addAdditionalToolTips(aList, aStack, aPlayer); + } + + } + + public static class BW_GT_MetaGen_Item_Hook extends MetaBaseItem { + + public static final HashSet<BWMetaItems.BW_GT_MetaGen_Item_Hook> sInstances = new HashSet<>(); + public final IIcon[] mIconList; + public final BitSet mEnabledItems; + + { + this.mIconList = new IIcon[Short.MAX_VALUE * 2]; + this.mEnabledItems = new BitSet(Short.MAX_VALUE); + } + + private BW_GT_MetaGen_Item_Hook(String aUnlocalized) { + super(aUnlocalized); + + this.setCreativeTab(new CreativeTabs("bw.MetaItems.0") { + + @Override + public Item getTabIconItem() { + return ItemRegistry.TAB; + } + }); + this.setHasSubtypes(true); + this.setMaxDamage(0); + BWMetaItems.BW_GT_MetaGen_Item_Hook.sInstances.add(this); + } + + @Override + public Long[] getElectricStats(ItemStack itemStack) { + return null; + } + + @Override + public Long[] getFluidContainerStats(ItemStack itemStack) { + return null; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final ItemStack addItem(int aID, String aEnglish, String aToolTip, Object... aRandomData) { + if (aToolTip == null) { + aToolTip = ""; + } + ItemStack rStack = new ItemStack(this, 1, aID); + GTLanguageManager.addStringLocalization(this.getUnlocalizedName(rStack) + ".name", aEnglish); + GTLanguageManager.addStringLocalization(this.getUnlocalizedName(rStack) + ".tooltip", aToolTip); + List<TCAspects.TC_AspectStack> tAspects = new ArrayList<>(); + this.mEnabledItems.set(aID); + Object[] var7 = aRandomData; + int var8 = aRandomData.length; + + int var9; + Object tRandomData; + for (var9 = 0; var9 < var8; ++var9) { + tRandomData = var7[var9]; + if (tRandomData instanceof SubTag && tRandomData == SubTag.NO_UNIFICATION) { + GTOreDictUnificator.addToBlacklist(rStack); + } + } + + var7 = aRandomData; + var8 = aRandomData.length; + + for (var9 = 0; var9 < var8; ++var9) { + tRandomData = var7[var9]; + if (tRandomData != null) { + boolean tUseOreDict = true; + + if (tRandomData instanceof IItemBehaviour) { + this.addItemBehavior(aID, (IItemBehaviour) tRandomData); + tUseOreDict = false; + } + + if (tRandomData instanceof IItemContainer) { + ((IItemContainer) tRandomData).set(rStack); + tUseOreDict = false; + } + + if (!(tRandomData instanceof SubTag)) { + if (tRandomData instanceof TCAspects.TC_AspectStack) { + ((TCAspects.TC_AspectStack) tRandomData).addToAspectList(tAspects); + } else if (tRandomData instanceof ItemData) { + if (GTUtility.isStringValid(tRandomData)) { + GTOreDictUnificator.registerOre(tRandomData, rStack); + } else { + GTOreDictUnificator.addItemData(rStack, (ItemData) tRandomData); + } + } else if (tUseOreDict) { + GTOreDictUnificator.registerOre(tRandomData, rStack); + } + } + } + } + + if (GregTechAPI.sThaumcraftCompat != null) { + GregTechAPI.sThaumcraftCompat.registerThaumcraftAspectsToItem(rStack, tAspects, false); + } + + return rStack; + } + + @Override + @SideOnly(Side.CLIENT) + public void getSubItems(Item var1, CreativeTabs aCreativeTab, List<ItemStack> aList) { + int j = this.mEnabledItems.length(); + + for (int i = 0; i < j; ++i) { + if (this.mEnabledItems.get(i)) { + ItemStack tStack = new ItemStack(this, 1, i); + this.isItemStackUsable(tStack); + aList.add(tStack); + } + } + } + + @Override + protected void addAdditionalToolTips(List<String> aList, ItemStack aStack, EntityPlayer aPlayer) { + super.addAdditionalToolTips(aList, aStack, aPlayer); + } + + @Override + public String getUnlocalizedName(ItemStack aStack) { + return this.getUnlocalizedName() + "." + aStack.getItemDamage(); + } + + @Override + public IIcon getIconFromDamage(int i) { + if (this.mEnabledItems.get(i)) return (IIcon) BWUtil.get2DCoordFrom1DArray(i, 0, 2, this.mIconList); + return null; + } + + @Override + public IIcon getIcon(ItemStack stack, int renderPass, EntityPlayer player, ItemStack usingItem, + int useRemaining) { + return this.getIconFromDamage(stack.getItemDamage()); + } + + @Override + public IIcon getIcon(ItemStack stack, int pass) { + return this.getIconFromDamage(stack.getItemDamage()); + } + } +} diff --git a/src/main/java/bartworks/system/material/CircuitGeneration/CircuitData.java b/src/main/java/bartworks/system/material/CircuitGeneration/CircuitData.java new file mode 100644 index 0000000000..fbf8600257 --- /dev/null +++ b/src/main/java/bartworks/system/material/CircuitGeneration/CircuitData.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018-2020 bartimaeusnek Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package bartworks.system.material.CircuitGeneration; + +import java.nio.ByteBuffer; + +import bartworks.util.MurmurHash3; + +public class CircuitData { + + private long aVoltage; + private int aSpecial; + private byte aTier; + + public CircuitData(long aVoltage, int aSpecial, byte aTier) { + this.aVoltage = aVoltage; + this.aSpecial = aSpecial; + this.aTier = aTier; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CircuitData that)) return false; + if (this.getaVoltage() != that.getaVoltage() || this.getaSpecial() != that.getaSpecial()) return false; + return this.getaTier() == that.getaTier(); + } + + @Override + public int hashCode() { + return MurmurHash3.murmurhash3_x86_32( + ByteBuffer.allocate(13) + .put(this.aTier) + .putInt(this.aSpecial) + .putLong(this.aVoltage) + .array(), + 0, + 13, + 31); + } + + public long getaVoltage() { + return this.aVoltage; + } + + public void setaVoltage(long aVoltage) { + this.aVoltage = aVoltage; + } + + public int getaSpecial() { + return this.aSpecial; + } + + public void setaSpecial(int aSpecial) { + this.aSpecial = aSpecial; + } + + public byte getaTier() { + return this.aTier; + } + + public void setaTier(byte aTier) { + this.aTier = aTier; + } +} diff --git a/src/main/java/bartworks/system/material/CircuitGeneration/CircuitImprintLoader.java b/src/main/java/bartworks/system/material/CircuitGeneration/CircuitImprintLoader.java new file mode 100644 index 0000000000..c81f62e2ab --- /dev/null +++ b/src/main/java/bartworks/system/material/CircuitGeneration/CircuitImprintLoader.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2018-2020 bartimaeusnek Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package bartworks.system.material.CircuitGeneration; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.oredict.OreDictionary; +import net.minecraftforge.oredict.ShapedOreRecipe; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + +import bartworks.API.recipe.BWNBTDependantCraftingRecipe; +import bartworks.API.recipe.BartWorksRecipeMaps; +import bartworks.ASM.BWCoreStaticReplacementMethodes; +import bartworks.common.configs.ConfigHandler; +import bartworks.system.material.WerkstoffLoader; +import bartworks.util.BWUtil; +import bartworks.util.Pair; +import cpw.mods.fml.common.registry.GameRegistry; +import gregtech.api.enums.ItemList; +import gregtech.api.enums.Materials; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.recipe.RecipeMaps; +import gregtech.api.util.GTModHandler; +import gregtech.api.util.GTOreDictUnificator; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.GTUtility; + +public class CircuitImprintLoader { + + public static short reverseIDs = Short.MAX_VALUE - 1; + + public static final ArrayListMultimap<NBTTagCompound, GTRecipe> recipeTagMap = ArrayListMultimap.create(); + public static final HashBiMap<Short, ItemList> circuitIIconRefs = HashBiMap.create(20); + public static final HashSet<ItemStack> blacklistSet = new HashSet<>(); + static final HashBiMap<CircuitData, ItemStack> bwCircuitTagMap = HashBiMap.create(20); + private static final HashSet<IRecipe> recipeWorldCache = new HashSet<>(); + private static final HashSet<GTRecipe> gtrecipeWorldCache = new HashSet<>(); + private static final HashSet<GTRecipe> ORIGINAL_CAL_RECIPES = new HashSet<>(); + private static final HashSet<GTRecipe> MODIFIED_CAL_RECIPES = new HashSet<>(); + + public static void run() { + HashSet<GTRecipe> toRem = new HashSet<>(); + HashSet<GTRecipe> toAdd = new HashSet<>(); + + deleteCALRecipesAndTags(); + rebuildCircuitAssemblerMap(toRem, toAdd); + exchangeRecipesInList(toRem, toAdd); + makeCircuitImprintRecipes(); + + toRem = null; + toAdd = null; + } + + private static void reAddOriginalRecipes() { + RecipeMaps.circuitAssemblerRecipes.getBackend() + .removeRecipes(MODIFIED_CAL_RECIPES); + ORIGINAL_CAL_RECIPES.forEach(RecipeMaps.circuitAssemblerRecipes::add); + ORIGINAL_CAL_RECIPES.clear(); + MODIFIED_CAL_RECIPES.clear(); + } + + private static void rebuildCircuitAssemblerMap(HashSet<GTRecipe> toRem, HashSet<GTRecipe> toAdd) { + reAddOriginalRecipes(); + RecipeMaps.circuitAssemblerRecipes.getAllRecipes() + .forEach(e -> CircuitImprintLoader.handleCircuitRecipeRebuilding(e, toRem, toAdd)); + } + + private static void handleCircuitRecipeRebuilding(GTRecipe circuitRecipe, HashSet<GTRecipe> toRem, + HashSet<GTRecipe> toAdd) { + ItemStack[] outputs = circuitRecipe.mOutputs; + boolean isOrePass = isCircuitOreDict(outputs[0]); + String unlocalizedName = outputs[0].getUnlocalizedName(); + if (isOrePass || unlocalizedName.contains("Circuit") || unlocalizedName.contains("circuit")) { + + CircuitImprintLoader.recipeTagMap + .put(CircuitImprintLoader.getTagFromStack(outputs[0]), circuitRecipe.copy()); + + Fluid solderIndalloy = FluidRegistry.getFluid("molten.indalloy140") != null + ? FluidRegistry.getFluid("molten.indalloy140") + : FluidRegistry.getFluid("molten.solderingalloy"); + + Fluid solderUEV = FluidRegistry.getFluid("molten.mutatedlivingsolder") != null + ? FluidRegistry.getFluid("molten.mutatedlivingsolder") + : FluidRegistry.getFluid("molten.solderingalloy"); + + if (circuitRecipe.mFluidInputs[0].isFluidEqual(Materials.SolderingAlloy.getMolten(0)) + || circuitRecipe.mFluidInputs[0].isFluidEqual(new FluidStack(solderIndalloy, 0)) + || circuitRecipe.mFluidInputs[0].isFluidEqual(new FluidStack(solderUEV, 0))) { + GTRecipe newRecipe = CircuitImprintLoader.reBuildRecipe(circuitRecipe); + if (newRecipe != null) BartWorksRecipeMaps.circuitAssemblyLineRecipes.addRecipe(newRecipe); + addCutoffRecipeToSets(toRem, toAdd, circuitRecipe); + } else if (circuitRecipe.mEUt > BWUtil.getTierVoltage(ConfigHandler.cutoffTier)) toRem.add(circuitRecipe); + } + } + + private static boolean isCircuitOreDict(ItemStack item) { + return BWUtil.isTieredCircuit(item) || BWUtil.getOreNames(item) + .stream() + .anyMatch(s -> "circuitPrimitiveArray".equals(s)); + } + + private static void exchangeRecipesInList(HashSet<GTRecipe> toRem, HashSet<GTRecipe> toAdd) { + toAdd.forEach(RecipeMaps.circuitAssemblerRecipes::add); + RecipeMaps.circuitAssemblerRecipes.getBackend() + .removeRecipes(toRem); + ORIGINAL_CAL_RECIPES.addAll(toRem); + MODIFIED_CAL_RECIPES.addAll(toAdd); + } + + private static void addCutoffRecipeToSets(HashSet<GTRecipe> toRem, HashSet<GTRecipe> toAdd, + GTRecipe circuitRecipe) { + if (circuitRecipe.mEUt > BWUtil.getTierVoltage(ConfigHandler.cutoffTier)) { + toRem.add(circuitRecipe); + toAdd.add(CircuitImprintLoader.makeMoreExpensive(circuitRecipe)); + } + } + + @SuppressWarnings("deprecation") + public static GTRecipe makeMoreExpensive(GTRecipe original) { + GTRecipe newRecipe = original.copy(); + for (ItemStack is : newRecipe.mInputs) { + if (!BWUtil.isTieredCircuit(is)) { + is.stackSize = Math.min(is.stackSize * 6, 64); + if (is.stackSize > is.getItem() + .getItemStackLimit() || is.stackSize > is.getMaxStackSize()) is.stackSize = is.getMaxStackSize(); + } + } + newRecipe.mFluidInputs[0].amount *= 4; + newRecipe.mDuration *= 4; + return newRecipe; + } + + public static GTRecipe reBuildRecipe(GTRecipe original) { + ItemStack[] in = new ItemStack[6]; + BiMap<ItemList, Short> inversed = CircuitImprintLoader.circuitIIconRefs.inverse(); + + for (int i = 0; i < 6; i++) { + try { + replaceCircuits(inversed, original, in, i); + replaceComponents(in, original, i); + } catch (ArrayIndexOutOfBoundsException e) { + break; + } catch (NullPointerException e) { + e.printStackTrace(); + } + } + + if (CircuitImprintLoader.checkForBlacklistedComponents(in)) { + return null; + } + + return new GTRecipe( + false, + in, + new ItemStack[] { getOutputMultiplied(original) }, + BWMetaItems.getCircuitParts() + .getStackWithNBT(CircuitImprintLoader.getTagFromStack(original.mOutputs[0]), 0, 0), + null, + original.mFluidInputs, + null, + original.mDuration * 12, + original.mEUt, + 0); + } + + private static ItemStack getOutputMultiplied(GTRecipe original) { + ItemStack out = original.copy() + .getOutput(0); + out.stackSize *= 16; + return out; + } + + private static void replaceCircuits(BiMap<ItemList, Short> inversed, GTRecipe original, ItemStack[] in, int index) { + for (ItemList il : inversed.keySet()) { + if (GTUtility.areStacksEqual(il.get(1), replaceCircuitParts(original.mInputs[index]))) { + in[index] = BWMetaItems.getCircuitParts() + .getStack(inversed.get(il), original.mInputs[index].stackSize); + } + } + } + + private static final List<Pair<ItemStack, ItemStack>> circuitPartsToReplace = Collections.unmodifiableList( + Arrays.asList( + new Pair<>(ItemList.Circuit_Parts_Resistor.get(1), ItemList.Circuit_Parts_ResistorSMD.get(1)), + new Pair<>(ItemList.Circuit_Parts_Diode.get(1), ItemList.Circuit_Parts_DiodeSMD.get(1)), + new Pair<>(ItemList.Circuit_Parts_Transistor.get(1), ItemList.Circuit_Parts_TransistorSMD.get(1)), + new Pair<>(ItemList.Circuit_Parts_Capacitor.get(1), ItemList.Circuit_Parts_CapacitorSMD.get(1)), + new Pair<>(ItemList.Circuit_Parts_Coil.get(1), ItemList.Circuit_Parts_InductorSMD.get(1)))); + + private static ItemStack replaceCircuitParts(ItemStack stack) { + for (Pair<ItemStack, ItemStack> pair : circuitPartsToReplace) { + if (GTUtility.areStacksEqual(pair.getKey(), stack)) { + ItemStack newStack = pair.getValue(); + newStack.stackSize = stack.stackSize; + return newStack; + } + } + return stack; + } + + @SuppressWarnings("deprecation") + private static void replaceComponents(ItemStack[] in, GTRecipe original, int index) + throws ArrayIndexOutOfBoundsException { + if (original.mInputs[index] != null && in[index] == null) { + // big wires + if (BWUtil.checkStackAndPrefix(original.mInputs[index]) + && GTOreDictUnificator.getAssociation(original.mInputs[index]).mPrefix == OrePrefixes.wireGt01) { + in[index] = GTOreDictUnificator.get( + OrePrefixes.wireGt16, + GTOreDictUnificator.getAssociation(original.mInputs[index]).mMaterial.mMaterial, + original.mInputs[index].stackSize); + // fine wires + } else if (BWUtil.checkStackAndPrefix(original.mInputs[index]) + && GTOreDictUnificator.getAssociation(original.mInputs[index]).mPrefix == OrePrefixes.wireFine) { + in[index] = GTOreDictUnificator.get( + OrePrefixes.wireGt04, + GTOreDictUnificator.getAssociation(original.mInputs[index]).mMaterial.mMaterial, + original.mInputs[index].stackSize); + if (in[index] == null) { + in[index] = GTOreDictUnificator.get( + OrePrefixes.wireFine, + GTOreDictUnificator.getAssociation(original.mInputs[index]).mMaterial.mMaterial, + original.mInputs[index].stackSize * 16); + } + // other components + } else { + in[index] = original.mInputs[index].copy(); + in[index].stackSize *= 16; + if (in[index].stackSize > in[index].getItem() + .getItemStackLimit() || in[index].stackSize > in[index].getMaxStackSize()) + in[index].stackSize = in[index].getMaxStackSize(); + } + } + } + + private static void makeCircuitImprintRecipes() { + removeOldRecipesFromRegistries(); + CircuitImprintLoader.recipeTagMap.keySet() + .forEach(e -> { + makeAndAddSlicingRecipe(e); + makeAndAddCraftingRecipes(e); + }); + } + + private static boolean checkForBlacklistedComponents(ItemStack[] itemStacks) { + for (ItemStack is : itemStacks) { + for (ItemStack is2 : CircuitImprintLoader.blacklistSet) { + if (GTUtility.areStacksEqual(is, is2)) return true; + } + } + return false; + } + + private static void removeOldRecipesFromRegistries() { + recipeWorldCache.forEach( + CraftingManager.getInstance() + .getRecipeList()::remove); + BWCoreStaticReplacementMethodes.clearRecentlyUsedRecipes(); + RecipeMaps.slicerRecipes.getBackend() + .removeRecipes(gtrecipeWorldCache); + recipeWorldCache.forEach(r -> { + try { + BWUtil.getGTBufferedRecipeList() + .remove(r); + } catch (Exception e) { + e.printStackTrace(); + } + }); + recipeWorldCache.clear(); + gtrecipeWorldCache.clear(); + } + + private static void makeAndAddSlicingRecipe(NBTTagCompound tag) { + ItemStack stack = CircuitImprintLoader.getStackFromTag(tag); + int eut = Integer.MAX_VALUE; + + for (GTRecipe recipe : CircuitImprintLoader.recipeTagMap.get(tag)) { + eut = Math.min(eut, recipe.mEUt); + } + + eut = Math.min( + eut, + BWUtil.getMachineVoltageFromTier( + BWUtil.getCircuitTierFromOreDictName( + OreDictionary.getOreName( + OreDictionary.getOreIDs(stack) != null && OreDictionary.getOreIDs(stack).length > 0 + ? OreDictionary.getOreIDs(stack)[0] + : -1)))); + GTRecipe slicingRecipe = new GTRecipe( + true, + new ItemStack[] { stack, ItemList.Shape_Slicer_Flat.get(0) }, + new ItemStack[] { BWMetaItems.getCircuitParts() + .getStackWithNBT(tag, 1, 1) }, + null, + null, + null, + null, + 300, + eut, + BWUtil.CLEANROOM); + gtrecipeWorldCache.add(slicingRecipe); + RecipeMaps.slicerRecipes.add(slicingRecipe); + } + + private static void makeAndAddCraftingRecipes(NBTTagCompound tag) { + ItemStack circuit = BWMetaItems.getCircuitParts() + .getStackWithNBT(tag, 0, 1); + Object[] imprintRecipe = { " X ", "GPG", " X ", 'P', BWMetaItems.getCircuitParts() + .getStackWithNBT(tag, 1, 1), 'G', WerkstoffLoader.Prasiolite.get(OrePrefixes.gemExquisite, 1), 'X', + BWMetaItems.getCircuitParts() + .getStack(3) }; + + IRecipe bwrecipe = new BWNBTDependantCraftingRecipe(circuit, imprintRecipe); + ShapedOreRecipe gtrecipe = BWUtil.createGTCraftingRecipe( + circuit, + GTModHandler.RecipeBits.DO_NOT_CHECK_FOR_COLLISIONS | GTModHandler.RecipeBits.KEEPNBT + | GTModHandler.RecipeBits.BUFFERED, + imprintRecipe); + + // Adds the actual recipe + recipeWorldCache.add(bwrecipe); + GameRegistry.addRecipe(bwrecipe); + // Adds the NEI visual recipe + recipeWorldCache.add(gtrecipe); + GameRegistry.addRecipe(gtrecipe); + } + + public static NBTTagCompound getTagFromStack(ItemStack stack) { + if (GTUtility.isStackValid(stack)) return BWUtil.setStackSize(stack.copy(), 1) + .writeToNBT(new NBTTagCompound()); + return new NBTTagCompound(); + } + + public static ItemStack getStackFromTag(NBTTagCompound tagCompound) { + return ItemStack.loadItemStackFromNBT(tagCompound); + } + + private static void deleteCALRecipesAndTags() { + BartWorksRecipeMaps.circuitAssemblyLineRecipes.getBackend() + .clearRecipes(); + recipeTagMap.clear(); + } +} diff --git a/src/main/java/bartworks/system/material/CircuitGeneration/CircuitPartLoader.java b/src/main/java/bartworks/system/material/CircuitGeneration/CircuitPartLoader.java new file mode 100644 index 0000000000..ea4d222cac --- /dev/null +++ b/src/main/java/bartworks/system/material/CircuitGeneration/CircuitPartLoader.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2018-2020 bartimaeusnek Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package bartworks.system.material.CircuitGeneration; + +import static gregtech.api.enums.ItemList.Circuit_Board_Advanced; +import static gregtech.api.enums.ItemList.Circuit_Board_Basic; +import static gregtech.api.enums.ItemList.Circuit_Board_Bio; +import static gregtech.api.enums.ItemList.Circuit_Board_Bio_Ultra; +import static gregtech.api.enums.ItemList.Circuit_Board_Coated; +import static gregtech.api.enums.ItemList.Circuit_Board_Coated_Basic; +import static gregtech.api.enums.ItemList.Circuit_Board_Elite; +import static gregtech.api.enums.ItemList.Circuit_Board_Epoxy; +import static gregtech.api.enums.ItemList.Circuit_Board_Epoxy_Advanced; +import static gregtech.api.enums.ItemList.Circuit_Board_Fiberglass; +import static gregtech.api.enums.ItemList.Circuit_Board_Fiberglass_Advanced; +import static gregtech.api.enums.ItemList.Circuit_Board_Multifiberglass; +import static gregtech.api.enums.ItemList.Circuit_Board_Multifiberglass_Elite; +import static gregtech.api.enums.ItemList.Circuit_Board_Optical; +import static gregtech.api.enums.ItemList.Circuit_Board_Phenolic; +import static gregtech.api.enums.ItemList.Circuit_Board_Phenolic_Good; +import static gregtech.api.enums.ItemList.Circuit_Board_Plastic; +import static gregtech.api.enums.ItemList.Circuit_Board_Plastic_Advanced; +import static gregtech.api.enums.ItemList.Circuit_Board_Wetware; +import static gregtech.api.enums.ItemList.Circuit_Board_Wetware_Extreme; +import static gregtech.api.enums.ItemList.Circuit_Chip_BioCPU; +import static gregtech.api.enums.ItemList.Circuit_Chip_Biocell; +import static gregtech.api.enums.ItemList.Circuit_Chip_CPU; +import static gregtech.api.enums.ItemList.Circuit_Chip_CrystalCPU; +import static gregtech.api.enums.ItemList.Circuit_Chip_CrystalSoC; +import static gregtech.api.enums.ItemList.Circuit_Chip_CrystalSoC2; +import static gregtech.api.enums.ItemList.Circuit_Chip_HPIC; +import static gregtech.api.enums.ItemList.Circuit_Chip_ILC; +import static gregtech.api.enums.ItemList.Circuit_Chip_LPIC; +import static gregtech.api.enums.ItemList.Circuit_Chip_NAND; +import static gregtech.api.enums.ItemList.Circuit_Chip_NOR; +import static gregtech.api.enums.ItemList.Circuit_Chip_NPIC; +import static gregtech.api.enums.ItemList.Circuit_Chip_NanoCPU; +import static gregtech.api.enums.ItemList.Circuit_Chip_NeuroCPU; +import static gregtech.api.enums.ItemList.Circuit_Chip_Optical; +import static gregtech.api.enums.ItemList.Circuit_Chip_PIC; +import static gregtech.api.enums.ItemList.Circuit_Chip_PPIC; +import static gregtech.api.enums.ItemList.Circuit_Chip_QPIC; +import static gregtech.api.enums.ItemList.Circuit_Chip_QuantumCPU; +import static gregtech.api.enums.ItemList.Circuit_Chip_Ram; +import static gregtech.api.enums.ItemList.Circuit_Chip_Simple_SoC; +import static gregtech.api.enums.ItemList.Circuit_Chip_SoC; +import static gregtech.api.enums.ItemList.Circuit_Chip_SoC2; +import static gregtech.api.enums.ItemList.Circuit_Chip_Stemcell; +import static gregtech.api.enums.ItemList.Circuit_Chip_UHPIC; +import static gregtech.api.enums.ItemList.Circuit_Chip_ULPIC; +import static gregtech.api.enums.ItemList.Circuit_Integrated; +import static gregtech.api.enums.ItemList.Circuit_Integrated_Good; +import static gregtech.api.enums.ItemList.Circuit_Parts_Advanced; +import static gregtech.api.enums.ItemList.Circuit_Parts_CapacitorASMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_CapacitorSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_CapacitorXSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_Chip_Bioware; +import static gregtech.api.enums.ItemList.Circuit_Parts_Crystal_Chip_Elite; +import static gregtech.api.enums.ItemList.Circuit_Parts_Crystal_Chip_Master; +import static gregtech.api.enums.ItemList.Circuit_Parts_Crystal_Chip_Wetware; +import static gregtech.api.enums.ItemList.Circuit_Parts_DiodeASMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_DiodeSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_DiodeXSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_GlassFiber; +import static gregtech.api.enums.ItemList.Circuit_Parts_InductorASMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_InductorSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_InductorXSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_PetriDish; +import static gregtech.api.enums.ItemList.Circuit_Parts_ResistorASMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_ResistorSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_ResistorXSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_TransistorASMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_TransistorSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_TransistorXSMD; +import static gregtech.api.enums.ItemList.Circuit_Parts_Vacuum_Tube; +import static gregtech.api.enums.ItemList.Circuit_Parts_Wiring_Advanced; +import static gregtech.api.enums.ItemList.Circuit_Parts_Wiring_Basic; +import static gregtech.api.enums.ItemList.Circuit_Parts_Wiring_Elite; +import static gregtech.api.enums.ItemList.Optical_Cpu_Containment_Housing; +import static gregtech.api.enums.ItemList.Optically_Compatible_Memory; +import static gregtech.api.enums.ItemList.Optically_Perfected_CPU; +import static gregtech.api.enums.ItemList.values; +import static gregtech.api.recipe.RecipeMaps.assemblerRecipes; +import static gregtech.api.util.GTRecipeBuilder.SECONDS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import net.minecraft.item.ItemStack; + +import bartworks.client.renderer.BWItemRenderer; +import cpw.mods.fml.common.FMLCommonHandler; +import gregtech.api.enums.GTValues; +import gregtech.api.enums.ItemList; +import gregtech.api.enums.Materials; +import gregtech.api.enums.TierEU; +import gregtech.api.util.GTLanguageManager; +import gregtech.api.util.GTUtility; + +public class CircuitPartLoader implements Runnable { + + @Override + public void run() { + CircuitPartLoader.makeCircuitParts(); + if (FMLCommonHandler.instance() + .getEffectiveSide() + .isClient()) new BWItemRenderer(); + } + + public static void makeCircuitParts() { + ItemList[] itemLists = values(); + for (ItemList single : itemLists) { + if (!single.hasBeenSet()) continue; + if (single.toString() + .contains("Wafer") + || single.toString() + .contains("Circuit_Silicon_Ingot") + || single.toString() + .contains("Raw") + || single.toString() + .contains("raw") + || single.toString() + .contains("Glass_Tube") + || single == Circuit_Parts_GlassFiber + || single == Circuit_Parts_Advanced + || single == Circuit_Parts_Wiring_Advanced + || single == Circuit_Parts_Wiring_Elite + || single == Circuit_Parts_Wiring_Basic + || single == Circuit_Integrated + || single == Circuit_Parts_PetriDish + || single == Circuit_Parts_Vacuum_Tube + || single == Circuit_Integrated_Good) { + + CircuitImprintLoader.blacklistSet.add(single.get(1)); + } + } + + for (ItemList single : CIRCUIT_PARTS) { + if (!single.hasBeenSet()) continue; + ItemStack itemStack = single.get(1); + if (!GTUtility.isStackValid(itemStack)) continue; + ArrayList<String> toolTip = new ArrayList<>(); + if (FMLCommonHandler.instance() + .getEffectiveSide() + .isClient()) + single.getItem() + .addInformation( + single.get(1) + .copy(), + null, + toolTip, + true); + String tt = !toolTip.isEmpty() ? toolTip.get(0) : ""; + // tt += "Internal Name = "+single; + String localised = GTLanguageManager + .getTranslation(GTLanguageManager.getTranslateableItemStackName(itemStack)); + BWMetaItems.getCircuitParts() + .addItem(CircuitImprintLoader.reverseIDs, "Wrap of " + localised + "s", tt); + + GTValues.RA.stdBuilder() + .itemInputs( + single.get(16) + .copy(), + GTUtility.getIntegratedCircuit(16)) + .itemOutputs( + BWMetaItems.getCircuitParts() + .getStack(CircuitImprintLoader.reverseIDs)) + .fluidInputs(Materials.Plastic.getMolten(72)) + .duration(30 * SECONDS) + .eut(TierEU.RECIPE_LV) + .addTo(assemblerRecipes); + + CircuitImprintLoader.circuitIIconRefs.put(CircuitImprintLoader.reverseIDs, single); + CircuitImprintLoader.reverseIDs--; + } + } + + /** + * Contains all the circuit parts we want to generate wrapped version of. New entries MUST be placed at the END of + * this list, to prevent id shift. + */ + private static final List<ItemList> CIRCUIT_PARTS = Collections.unmodifiableList( + Arrays.asList( + Circuit_Board_Basic, + Circuit_Board_Advanced, + Circuit_Board_Elite, + Circuit_Parts_Crystal_Chip_Elite, + Circuit_Parts_Crystal_Chip_Master, + Circuit_Board_Coated, + Circuit_Board_Coated_Basic, + Circuit_Board_Phenolic, + Circuit_Board_Phenolic_Good, + Circuit_Board_Epoxy, + Circuit_Board_Epoxy_Advanced, + Circuit_Board_Fiberglass, + Circuit_Board_Fiberglass_Advanced, + Circuit_Board_Multifiberglass_Elite, + Circuit_Board_Multifiberglass, + Circuit_Board_Wetware, + Circuit_Board_Wetware_Extreme, + Circuit_Board_Plastic, + Circuit_Board_Plastic_Advanced, + Circuit_Board_Bio, + Circuit_Board_Bio_Ultra, + Circuit_Parts_ResistorSMD, + Circuit_Parts_InductorSMD, + Circuit_Parts_DiodeSMD, + Circuit_Parts_TransistorSMD, + Circuit_Parts_CapacitorSMD, + Circuit_Parts_ResistorASMD, + Circuit_Parts_DiodeASMD, + Circuit_Parts_TransistorASMD, + Circuit_Parts_CapacitorASMD, + Circuit_Chip_ILC, + Circuit_Chip_Ram, + Circuit_Chip_NAND, + Circuit_Chip_NOR, + Circuit_Chip_CPU, + Circuit_Chip_SoC, + Circuit_Chip_SoC2, + Circuit_Chip_PIC, + Circuit_Chip_Simple_SoC, + Circuit_Chip_HPIC, + Circuit_Chip_UHPIC, + Circuit_Chip_ULPIC, + Circuit_Chip_LPIC, + Circuit_Chip_NPIC, + Circuit_Chip_PPIC, + Circuit_Chip_QPIC, + Circuit_Chip_NanoCPU, + Circuit_Chip_QuantumCPU, + Circuit_Chip_CrystalCPU, + Circuit_Chip_CrystalSoC, + Circuit_Chip_CrystalSoC2, + Circuit_Chip_NeuroCPU, + Circuit_Chip_BioCPU, + Circuit_Chip_Stemcell, + Circuit_Chip_Biocell, + Circuit_Parts_ResistorXSMD, + Circuit_Parts_DiodeXSMD, + Circuit_Parts_TransistorXSMD, + Circuit_Parts_CapacitorXSMD, + Circuit_Parts_InductorASMD, + Circuit_Parts_InductorXSMD, + Circuit_Chip_Optical, + Circuit_Board_Optical, + Optically_Perfected_CPU, + Optical_Cpu_Containment_Housing, + Optically_Compatible_Memory, + Circuit_Parts_Crystal_Chip_Wetware, + Circuit_Parts_Chip_Bioware)); +} |
