diff options
Diffstat (limited to 'src/main/java/gregtech/api/GregTech_API.java')
-rw-r--r-- | src/main/java/gregtech/api/GregTech_API.java | 1082 |
1 files changed, 1082 insertions, 0 deletions
diff --git a/src/main/java/gregtech/api/GregTech_API.java b/src/main/java/gregtech/api/GregTech_API.java new file mode 100644 index 0000000000..e80bc7345b --- /dev/null +++ b/src/main/java/gregtech/api/GregTech_API.java @@ -0,0 +1,1082 @@ +package gregtech.api; + +import static gregtech.api.enums.GT_Values.B; +import static gregtech.api.enums.GT_Values.L; +import static gregtech.api.enums.GT_Values.M; +import static gregtech.api.enums.Mods.IndustrialCraft2; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiFunction; +import java.util.function.IntFunction; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import javax.annotation.Nonnull; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; + +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.GT_Mod; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.Materials; +import gregtech.api.enums.SoundResource; +import gregtech.api.enums.Textures; +import gregtech.api.interfaces.IDamagableItem; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.internal.IGT_RecipeAdder; +import gregtech.api.interfaces.internal.IThaumcraftCompat; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable; +import gregtech.api.items.GT_CoolantCellIC_Item; +import gregtech.api.items.GT_CoolantCell_Item; +import gregtech.api.items.GT_Tool_Item; +import gregtech.api.metatileentity.BaseMetaTileEntity; +import gregtech.api.objects.GT_Cover_Default; +import gregtech.api.objects.GT_Cover_None; +import gregtech.api.objects.GT_HashSet; +import gregtech.api.objects.GT_ItemStack; +import gregtech.api.threads.GT_Runnable_Cable_Update; +import gregtech.api.threads.GT_Runnable_MachineBlockUpdate; +import gregtech.api.util.GT_CircuitryBehavior; +import gregtech.api.util.GT_Config; +import gregtech.api.util.GT_CoverBehavior; +import gregtech.api.util.GT_CoverBehaviorBase; +import gregtech.api.util.GT_CreativeTab; +import gregtech.api.util.GT_Log; +import gregtech.api.util.GT_ModHandler; +import gregtech.api.util.GT_OreDictUnificator; +import gregtech.api.util.GT_Utility; +import gregtech.api.util.item.ItemHolder; +import gregtech.api.world.GT_Worldgen; +import gregtech.common.GT_DummyWorld; +import gregtech.common.items.GT_IntegratedCircuit_Item; + +/** + * Please do not include this File in your Mod-download as it ruins compatibility, like with the IC2-API You may just + * copy those Functions into your Code, or better call them via reflection. + * <p/> + * The whole API is the basic construct of my Mod. Everything is dependent on it. I change things quite often so please + * don't include any File inside your Mod, even if it is an Interface. Since some Authors were stupid enough to break + * this simple Rule, I added Version checks to enforce it. + * <p/> + * In these Folders are many useful Functions. You can use them via reflection if you want. I know not everything is + * compilable due to APIs of other Mods, but these are easy to fix in your Setup. + * <p/> + * You can use this to learn about Modding, but I would recommend simpler Mods. You may even copy-paste Code from these + * API-Files into your Mod, as I have nothing against that, but you should look exactly at what you are copying. + * + * @author Gregorius Techneticies + */ +@SuppressWarnings("unused") // API class has legitimately unused methods and members +public class GregTech_API { + + /** + * @deprecated Use {@link GT_Values#M} + */ + @Deprecated + public static final long MATERIAL_UNIT = M; + /** + * @deprecated Use {@link GT_Values#L} + */ + @Deprecated + public static final long FLUID_MATERIAL_UNIT = L; + /** + * Fixes the HashMap Mappings for ItemStacks once the Server started + * <br> + * <br> + * NOTE: We use wildcards generics for the key because it could be for example {@link ItemStack} or + * {@link GT_ItemStack} + */ + public static final Collection<Map<?, ?>> sItemStackMappings = new ArrayList<>(); + public static final Collection<SetMultimap<? extends ItemHolder, ?>> itemStackMultiMaps = new ArrayList<>(); + + /** + * The MetaTileEntity-ID-List-Length + */ + public static final short MAXIMUM_METATILE_IDS = Short.MAX_VALUE - 1; + /** + * My Creative Tab + */ + public static final CreativeTabs TAB_GREGTECH = new GT_CreativeTab("Main", "Main"), + TAB_GREGTECH_MATERIALS = new GT_CreativeTab("Materials", "Materials"), + TAB_GREGTECH_ORES = new GT_CreativeTab("Ores", "Ores"); + /** + * A List of all registered MetaTileEntities + * <p/> + * 0 - 749 are used by GregTech. + * 750 - 999 are reserved for Alkalus. + * 1000 - 2047 are used by GregTech. + * 2048 - 2559 are reserved for OvermindDL. + * 2560 - 3071 are reserved for Immibis. + * 3072 - 3583 are reserved for LinusPhoenix. + * 3584 - 4095 are reserved for BloodyAsp. + * 4096 - 5095 are used for GregTech Frames. + * 5096 - 6099 are used for GregTech Pipes. + * 6100 - 8191 are used for GregTech Decoration Blocks. + * 8192 - 8703 are reserved for ZL123. + * 8704 - 9215 are reserved for Mr10Movie. + * 9216 - 9727 are used for GregTech Automation Machines. + * 9728 - 10239 are reserved for 28Smiles. + * 10240 - 10751 are reserved for VirMan. + * 10752 - 11263 are reserved for Briareos81. + * 11264 - 12000 are reserved for Quantum64. + * 12001 - 12500 are reserved for RedMage17. + * 12501 - 13000 are reserved for bartimaeusnek. + * 13001 - 13100 are reserved for Techlone. + * 13101 - 13500 are reserved for kekzdealer. + * 13501 - 14000 are reserved for glee8e. + * 14001 - 14100 are reserved for glowredman. + * 14101 - 14200 are reserved for MuXiu1997. + * 14201 - 14300 are reserved for kuba6000. + * 14301 - 14999 are currently free. + * 15000 - 16999 are reserved for TecTech. + * 17000 - 29999 are currently free. + * 30000 - 31999 are reserved for Alkalus. + * 32001 - 32766 are reserved for Glod. + * <p/> + * Contact me if you need a free ID-Range, which doesn't conflict with other Addons. You could make an ID-Config, + * but we all know what "stupid" customers think about conflicting ID's + */ + public static final IMetaTileEntity[] METATILEENTITIES = new IMetaTileEntity[MAXIMUM_METATILE_IDS]; + /** + * The Icon List for Covers + */ + public static final Map<GT_ItemStack, ITexture> sCovers = new ConcurrentHashMap<>(); + /** + * The List of Cover Behaviors for the Covers + */ + public static final Map<GT_ItemStack, GT_CoverBehaviorBase<?>> sCoverBehaviors = new ConcurrentHashMap<>(); + /** + * The List of Circuit Behaviors for the Redstone Circuit Block + */ + public static final Map<Integer, GT_CircuitryBehavior> sCircuitryBehaviors = new ConcurrentHashMap<>(); + /** + * The List of Blocks, which can conduct Machine Block Updates + */ + public static final Map<Block, Integer> sMachineIDs = new ConcurrentHashMap<>(); + /** + * The Redstone Frequencies + */ + public static final Map<Integer, Byte> sWirelessRedstone = new ConcurrentHashMap<>(); + /** + * The Advanced Redstone Frequencies + */ + public static final Map<String, Map<Integer, Map<Long, Byte>>> sAdvancedWirelessRedstone = new ConcurrentHashMap<>(); + + /** + * The IDSU Frequencies + */ + public static final Map<Integer, Integer> sIDSUList = new ConcurrentHashMap<>(); + /** + * A List of all Books, which were created using @GT_Utility.getWrittenBook the original Title is the Key Value + */ + public static final Map<String, ItemStack> sBookList = new ConcurrentHashMap<>(); + /** + * The List of all Sounds used in GT, indices are in the static Block at the bottom + * + * @deprecated Use {@link SoundResource} + */ + @Deprecated + public static final Map<Integer, String> sSoundList = SoundResource.asSoundList(); + /** + * The List of Tools, which can be used. Accepts regular damageable Items and Electric Items + */ + public static final GT_HashSet<GT_ItemStack> sToolList = new GT_HashSet<>(), sCrowbarList = new GT_HashSet<>(), + sScrewdriverList = new GT_HashSet<>(), sWrenchList = new GT_HashSet<>(), sSoftHammerList = new GT_HashSet<>(), + sHardHammerList = new GT_HashSet<>(), sWireCutterList = new GT_HashSet<>(), + sSolderingToolList = new GT_HashSet<>(), sSolderingMetalList = new GT_HashSet<>(), + sJackhammerList = new GT_HashSet<>(); + /** + * The List of Hazmat Armors + */ + public static final GT_HashSet<GT_ItemStack> sGasHazmatList = new GT_HashSet<>(), + sBioHazmatList = new GT_HashSet<>(), sFrostHazmatList = new GT_HashSet<>(), + sHeatHazmatList = new GT_HashSet<>(), sRadioHazmatList = new GT_HashSet<>(), + sElectroHazmatList = new GT_HashSet<>(); + + private static final Multimap<Integer, ItemStack> sRealConfigurationList = Multimaps + .newListMultimap(new TreeMap<>(), ArrayList::new); + private static final Map<Integer, List<ItemStack>> sConfigurationLists = new ConcurrentHashMap<>(); + private static final Map<Predicate<ItemStack>, BiFunction<ItemStack, EntityPlayerMP, ItemStack>> sRealCircuitProgrammerList = new LinkedHashMap<>(); + public static final Map<Predicate<ItemStack>, BiFunction<ItemStack, EntityPlayerMP, ItemStack>> sCircuitProgrammerList = Collections + .unmodifiableMap(sRealCircuitProgrammerList); + + /** + * The List of Dimensions, which are Whitelisted for the Teleporter. This list should not contain other Planets. + * Mystcraft Dimensions and other Dimensional Things should be allowed. Mystcraft and Twilight Forest are + * automatically considered a Dimension, without being in this List. + */ + public static final Collection<Integer> sDimensionalList = new HashSet<>(); + /** + * Lists of all the active World generation Features, these are getting Initialized in Postload! + */ + public static final List<GT_Worldgen> sWorldgenList = new ArrayList<>(); + /** + * A List containing all the Materials, which are somehow in use by GT and therefor receive a specific Set of Items. + */ + public static final Materials[] sGeneratedMaterials = new Materials[1000]; + /** + * This is the generic Cover behavior. Used for the default Covers, which have no Behavior. + */ + public static final GT_CoverBehavior sDefaultBehavior = new GT_Cover_Default(), sNoBehavior = new GT_Cover_None(); + /** + * For the API Version check + */ + public static volatile int VERSION = 509; + + /** + * @deprecated Use {@link GT_Values#RA} + */ + @SuppressWarnings("DeprecatedIsStillUsed") // Still need be initialized for backward compat + @Deprecated + public static IGT_RecipeAdder sRecipeAdder; + /** + * Registers Aspects to Thaumcraft. This Object might be {@code null} if Thaumcraft isn't installed. + */ + public static IThaumcraftCompat sThaumcraftCompat; + /** + * The Lists below are executed at their respective timings. Useful to do things at a particular moment in time. + * The Lists are not Threaded - a native Java interface is used for their execution. + * Add your "commands" in the constructor or in the static-code-block of your mod's Main class. + * Implement the method {@code run()}, and everything should work. + */ + public static List<Runnable> sBeforeGTPreload = new ArrayList<>(), sAfterGTPreload = new ArrayList<>(), + sBeforeGTLoad = new ArrayList<>(), sAfterGTLoad = new ArrayList<>(), sBeforeGTPostload = new ArrayList<>(), + sAfterGTPostload = new ArrayList<>(), sFirstWorldTick = new ArrayList<>(), + sBeforeGTServerstart = new ArrayList<>(), sAfterGTServerstart = new ArrayList<>(), + sBeforeGTServerstop = new ArrayList<>(), sAfterGTServerstop = new ArrayList<>(), + sGTBlockIconload = new ArrayList<>(), sGTItemIconload = new ArrayList<>(), sGTCompleteLoad = new ArrayList<>(); + /** + * The Icon Registers from Blocks and Items. They will get set right before the corresponding Icon Load Phase as + * executed in the Runnable List above. + */ + @SideOnly(Side.CLIENT) + public static IIconRegister sBlockIcons, sItemIcons; + /** + * The Configuration Objects + */ + public static GT_Config sMachineFile = null, sWorldgenFile = null, sMaterialProperties = null, sUnification = null, + sSpecialFile = null, sClientDataFile, sOPStuff = null; + + public static int TICKS_FOR_LAG_AVERAGING = 25, MILLISECOND_THRESHOLD_UNTIL_LAG_WARNING = 100; + /** + * Initialized by the Block creation. + */ + public static Block sBlockMachines; + + public static Block sBlockOres1, sBlockOresUb1, sBlockOresUb2, sBlockOresUb3, + /* sBlockGem, */ + sBlockMetal1, sBlockMetal2, sBlockMetal3, sBlockMetal4, sBlockMetal5, sBlockMetal6, sBlockMetal7, sBlockMetal8, + sBlockMetal9, sBlockGem1, sBlockGem2, sBlockGem3, sBlockReinforced; + public static Block sBlockGranites, sBlockConcretes, sBlockStones; + public static Block sBlockCasings1, sBlockCasings2, sBlockCasings3, sBlockCasings4, sBlockCasings5, sBlockCasings6, + sBlockCasings8, sBlockCasings9, sSolenoidCoilCasings; + public static Block sBlockLongDistancePipes; + public static Block sDroneRender; + /** + * Getting assigned by the Config + */ + public static boolean sTimber = true, sDrinksAlwaysDrinkable = false, sMultiThreadedSounds = false, + sDoShowAllItemsInCreative = false, sColoredGUI = true, sMachineMetalGUI = false, sConstantEnergy = true, + sMachineExplosions = true, sMachineFlammable = true, sMachineNonWrenchExplosions = true, + sMachineRainExplosions = true, sMachineThunderExplosions = true, sMachineFireExplosions = true, + sMachineWireFire = true, mOutputRF = false, mInputRF = false, meIOLoaded = false, mRFExplosions = false, + mServerStarted = false; + + @Deprecated + public static boolean mIC2Classic = false, mMagneticraft = false, mImmersiveEngineering = false, + mGTPlusPlus = false, mTranslocator = false, mTConstruct = false, mGalacticraft = false, mHodgepodge = false, + mAvaritia = false; + /** + * This is always set to true + */ + @Deprecated + public boolean mAE2 = true; + + public static int mEUtoRF = 360, mRFtoEU = 20; + + /** + * Option to not use MACHINE_METAL mixing into colors + */ + public static boolean sUseMachineMetal = false; + + public static boolean mUseOnlyGoodSolderingMaterials = false; + + private static final String aTextIC2Lower = IndustrialCraft2.ID.toLowerCase(Locale.ENGLISH); + /** + * Getting assigned by the Mod loading + */ + public static boolean sUnificationEntriesRegistered = false, sPreloadStarted = false, sPreloadFinished = false, + sLoadStarted = false, sLoadFinished = false, sPostloadStarted = false, sPostloadFinished = false; + + private static Class<BaseMetaTileEntity> sBaseMetaTileEntityClass = null; + + @SuppressWarnings("unchecked") + private static final IntFunction<TileEntity>[] teCreators = new IntFunction[16]; + + private static final Set<Class<?>> dummyWorlds = new HashSet<>(); + + static { + sItemStackMappings.add(sCovers); + sItemStackMappings.add(sCoverBehaviors); + + dummyWorlds.add(GT_DummyWorld.class); + tryAddDummyWorld("blockrenderer6343.client.world.DummyWorld"); + } + + private static void tryAddDummyWorld(String className) { + ClassLoader cl = GregTech_API.class.getClassLoader(); + Class<?> clazz; + try { + clazz = Class.forName(className, false, cl); + } catch (ReflectiveOperationException ex) { + return; + } + dummyWorlds.add(clazz); + } + + public static void addDummyWorld(Class<?> clazz) { + dummyWorlds.add(clazz); + } + + public static boolean isDummyWorld(@Nonnull World w) { + return dummyWorlds.contains(w.getClass()); + } + + /** + * You want OreDict-Unification for YOUR Mod/Addon, when GregTech is installed? This Function is especially for YOU. + * Call this Function after the load-Phase, as I register the most of the Unification at that Phase (Redpowers + * Storageblocks are registered at postload). A recommended use of this Function is inside your Recipe-System itself + * (if you have one), as the unification then makes 100% sure, that every added non-unificated Output gets + * automatically unificated. + * <p/> + * I will personally make sure, that only common prefixes of Ores get registered at the Unificator, as of now there + * are: pulp, dust, dustSmall, ingot, nugget, gem, ore and block If another Mod-Author messes these up, then it's + * not my fault, and it's especially not your fault. As these are commonly used prefixes. + * <p/> + * This Unificator-API-Function uses the same Functions I use, for unificating Items. So if there is something + * messed up (very unlikely), then everything is messed up. + * <p/> + * You shouldn't use this to unificate the Inputs of your Recipes, this is only meant for the Outputs. + * + * @param aOreStack the Stack you want to get unificated. It is stackSize Sensitive. + * @return Either an unificated Stack or the stack you toss in, but it should never be null, unless you throw a + * Null-Pointer into it. + */ + public static ItemStack getUnificatedOreDictStack(ItemStack aOreStack) { + if (!GregTech_API.sPreloadFinished) GT_Log.err.println( + "GregTech_API ERROR: " + aOreStack.getItem() + + "." + + aOreStack.getItemDamage() + + " - OreDict Unification Entries are not registered now, please call it in the postload phase."); + return GT_OreDictUnificator.get(true, aOreStack); + } + + /** + * Causes a Machineblock Update This update will cause surrounding MultiBlock Machines to update their + * Configuration. You should call this Function in @Block.breakBlock and in @Block.onBlockAdded of your Machine. + * + * @param aWorld is being the World + * @param aX is the X-Coord of the update causing Block + * @param aY is the Y-Coord of the update causing Block + * @param aZ is the Z-Coord of the update causing Block + */ + public static boolean causeMachineUpdate(World aWorld, int aX, int aY, int aZ) { + if (aWorld != null && !aWorld.isRemote && !isDummyWorld(aWorld)) { // World might be null during World-gen + GT_Runnable_MachineBlockUpdate.setMachineUpdateValues(aWorld, aX, aY, aZ); + return true; + } + return false; + } + + @SuppressWarnings("UnusedReturnValue") // Retains API method signature + public static boolean causeCableUpdate(World aWorld, int aX, int aY, int aZ) { + if (aWorld == null || aWorld.isRemote || isDummyWorld(aWorld)) { + return false; + } // World might be null during World-gen + GT_Runnable_Cable_Update.setCableUpdateValues(aWorld, aX, aY, aZ); + return true; + } + + /** + * Adds a Multi-Machine Block, like my Machine Casings for example. You should call @causeMachineUpdate + * in @Block.breakBlock and in {@link Block#onBlockAdded} of your registered Block. You don't need to register + * TileEntities which implement {@link IMachineBlockUpdateable} + * + * @param aBlock the Block + * @param aMeta the Metadata of the Blocks as Bitmask! -1 or ~0 for all Meta-values + */ + @SuppressWarnings("UnusedReturnValue") // Retains API method signature + public static boolean registerMachineBlock(Block aBlock, int aMeta) { + if (aBlock == null) return false; + if (GregTech_API.sThaumcraftCompat != null) + GregTech_API.sThaumcraftCompat.registerPortholeBlacklistedBlock(aBlock); + sMachineIDs.put(aBlock, aMeta); + return true; + } + + /** + * Like above but with boolean Parameters instead of a BitMask + */ + public static boolean registerMachineBlock(Block aBlock, boolean... aMeta) { + if (aBlock == null || aMeta == null || aMeta.length == 0) return false; + if (GregTech_API.sThaumcraftCompat != null) + GregTech_API.sThaumcraftCompat.registerPortholeBlacklistedBlock(aBlock); + int rMeta = 0; + for (byte i = 0; i < aMeta.length && i < 16; i++) if (aMeta[i]) rMeta |= B[i]; + sMachineIDs.put(aBlock, rMeta); + return true; + } + + /** + * if this Block is a Machine Update Conducting Block + */ + public static boolean isMachineBlock(Block aBlock, int aMeta) { + if (aBlock != null) { + Integer id = sMachineIDs.get(aBlock); + return id != null && (id & B[aMeta]) != 0; + } + return false; + } + + /** + * Creates a new Coolant Cell Item for your Nuclear Reactor + */ + public static Item constructCoolantCellItem(String aUnlocalized, String aEnglish, int aMaxStore) { + try { + return new GT_CoolantCellIC_Item(aUnlocalized, aEnglish, aMaxStore); + } catch (Throwable e) { + /* Do nothing */ + } + try { + return new GT_CoolantCell_Item(aUnlocalized, aEnglish, aMaxStore); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Generic_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug"); + } + + /** + * Creates a new Energy Armor Item + */ + public static Item constructElectricArmorItem(String aUnlocalized, String aEnglish, int aCharge, int aTransfer, + int aTier, int aDamageEnergyCost, int aSpecials, double aArmorAbsorbtionPercentage, boolean aChargeProvider, + int aType, int aArmorIndex) { + try { + return (Item) Class.forName("gregtechmod.api.items.GT_EnergyArmorIC_Item") + .getConstructors()[0].newInstance( + aUnlocalized, + aEnglish, + aCharge, + aTransfer, + aTier, + aDamageEnergyCost, + aSpecials, + aArmorAbsorbtionPercentage, + aChargeProvider, + aType, + aArmorIndex); + } catch (Throwable e) { + /* Do nothing */ + } + try { + return (Item) Class.forName("gregtechmod.api.items.GT_EnergyArmor_Item") + .getConstructors()[0].newInstance( + aUnlocalized, + aEnglish, + aCharge, + aTransfer, + aTier, + aDamageEnergyCost, + aSpecials, + aArmorAbsorbtionPercentage, + aChargeProvider, + aType, + aArmorIndex); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Generic_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug"); + } + + /** + * Creates a new Energy Battery Item + */ + public static Item constructElectricEnergyStorageItem(String aUnlocalized, String aEnglish, int aCharge, + int aTransfer, int aTier, int aEmptyID, int aFullID) { + try { + return (Item) Class.forName("gregtechmod.api.items.GT_EnergyStoreIC_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aCharge, aTransfer, aTier, aEmptyID, aFullID); + } catch (Throwable e) { + /* Do nothing */ + } + try { + return (Item) Class.forName("gregtechmod.api.items.GT_EnergyStore_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aCharge, aTransfer, aTier, aEmptyID, aFullID); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Generic_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug"); + } + + /** + * Creates a new Hard Hammer Item + */ + public static GT_Tool_Item constructHardHammerItem(String aUnlocalized, String aEnglish, int aMaxDamage, + int aEntityDamage) { + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_HardHammer_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aMaxDamage, aEntityDamage); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Tool_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug", + aMaxDamage, + aEntityDamage, + false); + } + + /** + * Creates a new Crowbar Item + */ + public static GT_Tool_Item constructCrowbarItem(String aUnlocalized, String aEnglish, int aMaxDamage, + int aEntityDamage) { + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_CrowbarRC_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aMaxDamage, aEntityDamage); + } catch (Throwable e) { + /* Do nothing */ + } + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_Crowbar_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aMaxDamage, aEntityDamage); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Tool_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug", + aMaxDamage, + aEntityDamage, + false); + } + + /** + * Creates a new Wrench Item + */ + public static GT_Tool_Item constructWrenchItem(String aUnlocalized, String aEnglish, int aMaxDamage, + int aEntityDamage, int aDisChargedGTID) { + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_Wrench_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aMaxDamage, aEntityDamage, aDisChargedGTID); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Tool_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug", + aMaxDamage, + aEntityDamage, + false); + } + + /** + * Creates a new electric Screwdriver Item + */ + public static GT_Tool_Item constructElectricScrewdriverItem(String aUnlocalized, String aEnglish, int aMaxDamage, + int aEntityDamage, int aDisChargedGTID) { + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_ScrewdriverIC_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aMaxDamage, aEntityDamage, aDisChargedGTID); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Tool_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug", + aMaxDamage, + aEntityDamage, + false); + } + + /** + * Creates a new electric Wrench Item + */ + public static GT_Tool_Item constructElectricWrenchItem(String aUnlocalized, String aEnglish, int aMaxDamage, + int aEntityDamage, int aDisChargedGTID) { + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_WrenchIC_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aMaxDamage, aEntityDamage, aDisChargedGTID); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Tool_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug", + aMaxDamage, + aEntityDamage, + false); + } + + /** + * Creates a new electric Saw Item + */ + public static GT_Tool_Item constructElectricSawItem(String aUnlocalized, String aEnglish, int aMaxDamage, + int aEntityDamage, int aToolQuality, float aToolStrength, int aEnergyConsumptionPerBlockBreak, + int aDisChargedGTID) { + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_SawIC_Item") + .getConstructors()[0].newInstance( + aUnlocalized, + aEnglish, + aMaxDamage, + aEntityDamage, + aToolQuality, + aToolStrength, + aEnergyConsumptionPerBlockBreak, + aDisChargedGTID); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Tool_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug", + aMaxDamage, + aEntityDamage, + false); + } + + /** + * Creates a new electric Drill Item + */ + public static GT_Tool_Item constructElectricDrillItem(String aUnlocalized, String aEnglish, int aMaxDamage, + int aEntityDamage, int aToolQuality, float aToolStrength, int aEnergyConsumptionPerBlockBreak, + int aDisChargedGTID) { + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_DrillIC_Item") + .getConstructors()[0].newInstance( + aUnlocalized, + aEnglish, + aMaxDamage, + aEntityDamage, + aToolQuality, + aToolStrength, + aEnergyConsumptionPerBlockBreak, + aDisChargedGTID); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Tool_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug", + aMaxDamage, + aEntityDamage, + false); + } + + /** + * Creates a new electric Soldering Tool + */ + public static GT_Tool_Item constructElectricSolderingToolItem(String aUnlocalized, String aEnglish, int aMaxDamage, + int aEntityDamage, int aDisChargedGTID) { + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_SolderingToolIC_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aMaxDamage, aEntityDamage, aDisChargedGTID); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Tool_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug", + aMaxDamage, + aEntityDamage, + false); + } + + /** + * Creates a new empty electric Tool + */ + public static GT_Tool_Item constructEmptyElectricToolItem(String aUnlocalized, String aEnglish, int aMaxDamage, + int aChargedGTID) { + try { + return (GT_Tool_Item) Class.forName("gregtechmod.api.items.GT_EmptyToolIC_Item") + .getConstructors()[0].newInstance(aUnlocalized, aEnglish, aMaxDamage, aChargedGTID); + } catch (Throwable e) { + /* Do nothing */ + } + return new gregtech.api.items.GT_Tool_Item( + aUnlocalized, + aEnglish, + "Doesn't work as intended, this is a Bug", + aMaxDamage, + 0, + false); + } + + /** + * Provides a new BaseMetaTileEntity. Because some interfaces are not always loaded (Buildcraft, Universal + * Electricity) we have to use invocation at the constructor of the BaseMetaTileEntity. + */ + public static BaseMetaTileEntity constructBaseMetaTileEntity() { + if (sBaseMetaTileEntityClass == null) { + try { + return (sBaseMetaTileEntityClass = BaseMetaTileEntity.class).getDeclaredConstructor() + .newInstance(); + } catch (Throwable ignored) {} + } + + try { + return sBaseMetaTileEntityClass.getDeclaredConstructor() + .newInstance(); + } catch (Throwable e) { + GT_Log.err.println("GT_Mod: Fatal Error occurred while initializing TileEntities, crashing Minecraft."); + e.printStackTrace(GT_Log.err); + throw new RuntimeException(e); + } + } + + /** + * Register a new ItemStack as configuration circuits. Duplicates or invalid stacks will be silently ignored. + */ + public static void registerConfigurationCircuit(ItemStack aStack) { + registerConfigurationCircuit(aStack, 0); + } + + /** + * Register a new ItemStack as configuration circuits. Duplicates or invalid stacks will be silently ignored. + * + * @param minTier the minimal tier this circuit can be offered for free, e.g. normal configuration circuit is + * available in LV+ single blocks, GT++ breakthrough circuit is offered in HV+ single blocks + */ + public static void registerConfigurationCircuit(ItemStack aStack, int minTier) { + if (GT_Utility.isStackInvalid(aStack)) return; + for (ItemStack tRegistered : sRealConfigurationList.values()) + if (GT_Utility.areStacksEqual(tRegistered, aStack)) return; + ItemStack stack = GT_Utility.copyAmount(0, aStack); + sRealConfigurationList.put(minTier, stack); + for (Map.Entry<Integer, List<ItemStack>> e : sConfigurationLists.entrySet()) { + if (e.getKey() >= minTier) { + e.getValue() + .add(stack); + e.getValue() + .sort(getConfigurationCircuitsComparator()); + } + } + } + + /** + * Get a list of Configuration circuits. These stacks will have a stack size of 0. Use + * {@link #registerConfigurationCircuit(ItemStack, int)} or its overload to add to this list. + * + * @param machineTier The voltage tier where this list will be used. use Integer.MAX_VALUE to get all circuits + * @return An unmodifiable view of actual list. DO NOT MODIFY THE ItemStacks! + */ + public static List<ItemStack> getConfigurationCircuitList(int machineTier) { + return Collections.unmodifiableList( + sConfigurationLists.computeIfAbsent( + machineTier, + (t) -> sRealConfigurationList.entries() + .stream() + .filter(e -> e.getKey() <= machineTier) + .map(Map.Entry::getValue) + .sorted(getConfigurationCircuitsComparator()) + .collect(Collectors.toList()))); + } + + public static Comparator<ItemStack> getConfigurationCircuitsComparator() { + return Comparator.comparingInt((ItemStack is) -> { + // By default, the Programmed Circuit should be the earliest configuration circuit to which the + // player is exposed + if (GT_Mod.gregtechproxy.mCircuitsOrder.isEmpty()) + return is.getItem() instanceof GT_IntegratedCircuit_Item ? 0 : 1; + return GT_Mod.gregtechproxy.mCircuitsOrder + .getOrDefault(String.valueOf(GameRegistry.findUniqueIdentifierFor(is.getItem())), Integer.MAX_VALUE); + }) + .thenComparing(ItemStack::getUnlocalizedName) + .thenComparing(ItemStack::getItemDamage); + } + + public static void registerCircuitProgrammer(ItemStack stack, boolean ignoreNBT, boolean useContainer) { + registerCircuitProgrammer(rhs -> GT_Utility.areStacksEqual(stack, rhs, ignoreNBT), useContainer); + } + + public static void registerCircuitProgrammer(Predicate<ItemStack> predicate, boolean useContainer) { + sRealCircuitProgrammerList.put( + predicate, + useContainer ? (s, p) -> s.getItem() + .getContainerItem(s) : (s, p) -> s); + } + + public static void registerCircuitProgrammer(Predicate<ItemStack> predicate, + BiFunction<ItemStack, EntityPlayerMP, ItemStack> doDamage) { + sRealCircuitProgrammerList.put(predicate, doDamage); + } + + public static void registerCover(ItemStack aStack, ITexture aCover, GT_CoverBehavior aBehavior) { + registerCover(aStack, aCover, (GT_CoverBehaviorBase<?>) aBehavior); + } + + public static void registerCover(ItemStack aStack, ITexture aCover, GT_CoverBehaviorBase<?> aBehavior) { + if (!sCovers.containsKey(new GT_ItemStack(aStack))) sCovers.put( + new GT_ItemStack(aStack), + aCover == null || !aCover.isValidTexture() ? Textures.BlockIcons.ERROR_RENDERING[0] : aCover); + if (aBehavior != null) sCoverBehaviors.put(new GT_ItemStack(aStack), aBehavior); + } + + public static void registerCoverBehavior(ItemStack aStack, GT_CoverBehavior aBehavior) { + registerCoverBehavior(aStack, (GT_CoverBehaviorBase<?>) aBehavior); + } + + public static void registerCoverBehavior(ItemStack aStack, GT_CoverBehaviorBase<?> aBehavior) { + sCoverBehaviors.put(new GT_ItemStack(aStack), aBehavior == null ? sDefaultBehavior : aBehavior); + } + + /** + * Registers multiple Cover Items. I use that for the OreDict Functionality. + * + * @param aBehavior can be null + */ + public static void registerCover(Collection<ItemStack> aStackList, ITexture aCover, GT_CoverBehavior aBehavior) { + registerCover(aStackList, aCover, (GT_CoverBehaviorBase<?>) aBehavior); + } + + /** + * Registers multiple Cover Items. I use that for the OreDict Functionality. + * + * @param aBehavior can be null + */ + public static void registerCover(Collection<ItemStack> aStackList, ITexture aCover, + GT_CoverBehaviorBase<?> aBehavior) { + if (aCover.isValidTexture()) + aStackList.forEach(tStack -> GregTech_API.registerCover(tStack, aCover, aBehavior)); + } + + /** + * returns a Cover behavior, guaranteed to not return null after preload + */ + @Deprecated + public static GT_CoverBehavior getCoverBehavior(ItemStack aStack) { + if (aStack == null || aStack.getItem() == null) return sNoBehavior; + GT_CoverBehaviorBase<?> rCover = sCoverBehaviors.get(new GT_ItemStack(aStack)); + if (!(rCover instanceof GT_CoverBehavior)) return sDefaultBehavior; + return (GT_CoverBehavior) rCover; + } + + /** + * returns a Cover behavior, guaranteed to not return null after preload + * + * @return The Cover behavior + */ + public static GT_CoverBehaviorBase<?> getCoverBehaviorNew(ItemStack aStack) { + if (aStack == null || aStack.getItem() == null) return sNoBehavior; + GT_CoverBehaviorBase<?> rCover = sCoverBehaviors.get(new GT_ItemStack(aStack)); + if (rCover != null) return rCover; + rCover = sCoverBehaviors.get(new GT_ItemStack(aStack, true)); + if (rCover != null) return rCover; + return sDefaultBehavior; + } + + /** + * returns a Cover behavior, guaranteed to not return null + */ + @Deprecated + public static GT_CoverBehavior getCoverBehavior(int aStack) { + if (aStack == 0) return sNoBehavior; + return getCoverBehavior(GT_Utility.intToStack(aStack)); + } + + /** + * returns a Cover behavior, guaranteed to not return null + */ + public static GT_CoverBehaviorBase<?> getCoverBehaviorNew(int aStack) { + if (aStack == 0) return sNoBehavior; + return getCoverBehaviorNew(GT_Utility.intToStack(aStack)); + } + + /** + * Register a Wrench to be usable on GregTech Machines. The Wrench MUST have some kind of Durability unlike certain + * Buildcraft Wrenches. + * <p/> + * You need to register Tools in the Load Phase, because otherwise the Auto-detection will assign a Tool Type in + * certain Cases during postload (When IToolWrench or similar Interfaces are implemented). + * <p/> + * ----- + * <p/> + * Returning true at isDamageable was a great Idea, KingLemming. Well played. Since the OmniWrench is just a + * Single-Item-Mod, people can choose if they want your infinite durability or not. So that's not really a Problem. + * I even have a new Config to auto-disable most infinite BC Wrenches (but that one is turned off). + * <p/> + * One last Bug for you to fix: My Auto-registration detects Railcraft's Crowbars, Buildcraft's Wrenches and alike, + * due to their Interfaces. Guess what now became a Crowbar by accident. Try registering the Wrench at the load + * phase to prevent things like that from happening. Yes, I know that "You need to register Tools in the Load + * Phase"-Part wasn't there before this. Sorry about that. + */ + public static boolean registerWrench(ItemStack aTool) { + return registerTool(aTool, sWrenchList); + } + + /** + * Register a Crowbar to extract Covers from Machines Crowbars are NOT Wrenches btw. + * <p/> + * You need to register Tools in the Load Phase, because otherwise the Auto-detection will assign a Tool Type in + * certain Cases during postload (When IToolWrench or similar Interfaces are implemented). + */ + public static boolean registerCrowbar(ItemStack aTool) { + return registerTool(aTool, sCrowbarList); + } + + /** + * Register a Screwdriver to interact directly with Machines and Covers Did I mention, that it is intentionally not + * possible to make a Multi-tool, which doesn't switch ItemID (like a Mode) all the time? + * <p/> + * You need to register Tools in the Load Phase, because otherwise the Auto-detection will assign a Tool Type in + * certain Cases during postload (When IToolWrench or similar Interfaces are implemented). + */ + @SuppressWarnings("UnusedReturnValue") // Retains API method signature + public static boolean registerScrewdriver(ItemStack aTool) { + return registerTool(aTool, sScrewdriverList); + } + + /** + * Register a Soft Hammer to interact with Machines + * <p/> + * You need to register Tools in the Load Phase, because otherwise the Auto-detection will assign a Tool Type in + * certain Cases during postload (When IToolWrench or similar Interfaces are implemented). + */ + public static boolean registerSoftHammer(ItemStack aTool) { + return registerTool(aTool, sSoftHammerList); + } + + /** + * Register a Hard Hammer to interact with Machines + * <p/> + * You need to register Tools in the Load Phase, because otherwise the Auto-detection will assign a Tool Type in + * certain Cases during postload (When IToolWrench or similar Interfaces are implemented). + */ + public static boolean registerHardHammer(ItemStack aTool) { + return registerTool(aTool, sHardHammerList); + } + + /** + * Register a Wire Cutter to interact with Machines + * <p/> + * You need to register Tools in the Load Phase, because otherwise the Auto-detection will assign a Tool Type in + * certain Cases during postload (When IToolWrench or similar Interfaces are implemented). + */ + public static boolean registerWireCutter(ItemStack aTool) { + return registerTool(aTool, sWireCutterList); + } + + /** + * Register a Soldering Tool to interact with Machines + * <p/> + * You need to register Tools in the Load Phase, because otherwise the Auto-detection will assign a Tool Type in + * certain Cases during postload (When IToolWrench or similar Interfaces are implemented). + */ + @SuppressWarnings("UnusedReturnValue") // Retains API method signature + public static boolean registerSolderingTool(ItemStack aTool) { + return registerTool(aTool, sSolderingToolList); + } + + /** + * Register a Soldering Tin to interact with Soldering Tools + * <p/> + * You need to register Tools in the Load Phase, because otherwise the Auto-detection will assign a Tool Type in + * certain Cases during postload (When IToolWrench or similar Interfaces are implemented). + */ + @SuppressWarnings("UnusedReturnValue") // Retains API method signature + public static boolean registerSolderingMetal(ItemStack aTool) { + return registerTool(aTool, sSolderingMetalList); + } + + /** + * Generic Function to add Tools to the Lists. Contains all sanity Checks for Tools, like preventing one Tool from + * being registered for multiple purposes as controls would override each other. + */ + public static boolean registerTool(ItemStack aTool, Collection<GT_ItemStack> aToolList) { + if (aTool == null || GT_Utility.isStackInList(aTool, sToolList) + || (!aTool.getItem() + .isDamageable() && !GT_ModHandler.isElectricItem(aTool) + && !(aTool.getItem() instanceof IDamagableItem))) + return false; + aToolList.add(new GT_ItemStack(GT_Utility.copyAmount(1, aTool))); + sToolList.add(new GT_ItemStack(GT_Utility.copyAmount(1, aTool))); + return true; + } + + /** + * Sets the {@link IIconRegister} for Block Icons + * + * @param aIconRegister The {@link IIconRegister} Icon Register + */ + @SideOnly(Side.CLIENT) + public static void setBlockIconRegister(IIconRegister aIconRegister) { + sBlockIcons = aIconRegister; + } + + /** + * Sets the {@link IIconRegister} for Items Icons + * + * @param aIconRegister The {@link IIconRegister} Icon Register + */ + @SideOnly(Side.CLIENT) + public static void setItemIconRegister(IIconRegister aIconRegister) { + GregTech_API.sItemIcons = aIconRegister; + } + + public static void registerTileEntityConstructor(int meta, IntFunction<TileEntity> constructor) { + if (meta < 0 || meta > 15 || constructor == null) throw new IllegalArgumentException(); + if (teCreators[meta] != null) throw new IllegalStateException( + "previous constructor: " + teCreators[meta] + " new constructor: " + constructor + " meta:" + meta); + teCreators[meta] = constructor; + } + + public static TileEntity createTileEntity(int meta) { + meta = GT_Utility.clamp(meta, 0, 15); + if (teCreators[meta] == null) return null; + return teCreators[meta].apply(meta); + } +} |