aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gtPlusPlus/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gtPlusPlus/api')
-rw-r--r--src/main/java/gtPlusPlus/api/damage/DamageTeslaTower.java24
-rw-r--r--src/main/java/gtPlusPlus/api/enums/ParticleNames.java37
-rw-r--r--src/main/java/gtPlusPlus/api/enums/Quality.java62
-rw-r--r--src/main/java/gtPlusPlus/api/helpers/GregtechPlusPlus_API.java203
-rw-r--r--src/main/java/gtPlusPlus/api/helpers/MaterialHelper.java76
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/IChunkLoader.java33
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/IComparableRecipe.java8
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/IEntityCatcher.java21
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/IGeneratorWorld.java17
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/IGregtechPacketEntity.java13
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/IGregtechPower.java145
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/ILazyCoverable.java144
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/IPlugin.java40
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/IRandomGenerator.java55
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/ITexturedBlock.java14
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/ITileTooltip.java7
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/IToolable.java17
-rw-r--r--src/main/java/gtPlusPlus/api/interfaces/RunnableWithInfo.java12
-rw-r--r--src/main/java/gtPlusPlus/api/objects/GregtechException.java28
-rw-r--r--src/main/java/gtPlusPlus/api/objects/Logger.java179
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/AutoMap.java345
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/ConcurrentHashSet.java18
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/ConcurrentSet.java53
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/FlexiblePair.java39
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/ObjMap.java285
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/Pair.java35
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/Quad.java45
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/ReverseAutoMap.java175
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/Triplet.java27
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/TypeCounter.java178
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/WeightedCollection.java102
-rw-r--r--src/main/java/gtPlusPlus/api/objects/data/weakref/WeakAutoMap.java12
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/AABB.java65
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/BTF_FluidTank.java188
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/BTF_Inventory.java228
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/BlockPos.java250
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/CubicObject.java62
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/DimChunkPos.java52
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/FakeBlockPos.java253
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/FakeWorld.java173
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/FluidGT6.java31
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/FormattedTooltipString.java25
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/GenericStack.java42
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/ItemPackage.java58
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/ItemStackData.java35
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/NoConflictGTRecipeMap.java123
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/SafeTexture.java64
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/ShapedRecipe.java250
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/TexturePackage.java55
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/ThreadPooCollector.java111
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoEUBonusMultiBehaviour.java27
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoOutputBonusMultiBehaviour.java27
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoSpeedBonusMultiBehaviour.java27
-rw-r--r--src/main/java/gtPlusPlus/api/objects/minecraft/multi/SpecialMultiBehaviour.java44
-rw-r--r--src/main/java/gtPlusPlus/api/objects/random/CSPRNG_DO_NOT_USE.java271
-rw-r--r--src/main/java/gtPlusPlus/api/objects/random/UUIDGenerator.java449
-rw-r--r--src/main/java/gtPlusPlus/api/objects/random/XSTR.java278
-rw-r--r--src/main/java/gtPlusPlus/api/plugin/Sample_Plugin.java47
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/energy/IThermalConnection.java7
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/energy/IThermalContainerItem.java15
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/energy/IThermalHandler.java15
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/energy/IThermalProvider.java13
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/energy/IThermalReceiver.java13
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/energy/IThermalStorage.java13
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/energy/ThermalStorage.java116
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/energy/ThermalStorageAdv.java34
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/sample/ItemThermalContainer.java84
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/sample/TileThermalHandler.java42
-rw-r--r--src/main/java/gtPlusPlus/api/thermal/tileentity/IThermalInfo.java13
69 files changed, 6049 insertions, 0 deletions
diff --git a/src/main/java/gtPlusPlus/api/damage/DamageTeslaTower.java b/src/main/java/gtPlusPlus/api/damage/DamageTeslaTower.java
new file mode 100644
index 0000000000..f35c9cbc6b
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/damage/DamageTeslaTower.java
@@ -0,0 +1,24 @@
+package gtPlusPlus.api.damage;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.util.ChatComponentTranslation;
+import net.minecraft.util.IChatComponent;
+
+import gtPlusPlus.core.world.damage.BaseCustomDamageSource;
+
+public class DamageTeslaTower extends BaseCustomDamageSource{
+
+ public DamageTeslaTower(Entity transmitter) {
+ super("plasmabolt", transmitter, null);
+ this.setDamageBypassesArmor();
+ this.setDamageIsAbsolute();
+ }
+
+ @Override
+ public IChatComponent func_151519_b(EntityLivingBase target) {
+ String s = "death.attack." + this.damageType;
+ return new ChatComponentTranslation(s, target.getCommandSenderName(), "Plasma");
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/enums/ParticleNames.java b/src/main/java/gtPlusPlus/api/enums/ParticleNames.java
new file mode 100644
index 0000000000..d082cd6779
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/enums/ParticleNames.java
@@ -0,0 +1,37 @@
+package gtPlusPlus.api.enums;
+
+public enum ParticleNames {
+
+ explode,
+ largeexplode,
+ hugeexplosion,
+ bubble,
+ splash,
+ suspended,
+ depthsuspend,
+ crit,
+ magicCrit,
+ smoke,
+ largesmoke,
+ spell,
+ instantSpell,
+ mobSpell,
+ dripWater,
+ dripLava,
+ townaura,
+ note,
+ portal,
+ enchantmenttable,
+ flame,
+ lava,
+ footstep,
+ cloud,
+ reddust,
+ snowballpoof,
+ snowshovel,
+ slime,
+ heart,
+ iconcrack_,
+ tilecrack_;
+
+}
diff --git a/src/main/java/gtPlusPlus/api/enums/Quality.java b/src/main/java/gtPlusPlus/api/enums/Quality.java
new file mode 100644
index 0000000000..050f335b5e
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/enums/Quality.java
@@ -0,0 +1,62 @@
+package gtPlusPlus.api.enums;
+
+import net.minecraft.util.EnumChatFormatting;
+
+import gtPlusPlus.core.util.math.MathUtils;
+
+public enum Quality {
+
+ // Magic Blue
+ // Rare Yellow
+ // Set Green
+ // Unique Gold/Purple
+ // Trade-off Brown
+
+ POOR("Poor", EnumChatFormatting.GRAY), COMMON("Common", EnumChatFormatting.WHITE), UNCOMMON("Uncommon",
+ EnumChatFormatting.DARK_GREEN), MAGIC("Magic", EnumChatFormatting.BLUE), RARE("Rare",
+ EnumChatFormatting.YELLOW), UNIQUE("Unique", EnumChatFormatting.GOLD), ARTIFACT("Artifact",
+ EnumChatFormatting.AQUA), SET("Set Piece", EnumChatFormatting.GREEN), TRADEOFF("Trade-off",
+ EnumChatFormatting.DARK_RED), EPIC("Epic", EnumChatFormatting.LIGHT_PURPLE);
+
+ private String LOOT;
+ private EnumChatFormatting COLOUR;
+
+ private Quality(final String lootTier, final EnumChatFormatting tooltipColour) {
+ this.LOOT = lootTier;
+ this.COLOUR = tooltipColour;
+ }
+
+ public String getQuality() {
+ return this.LOOT;
+ }
+
+ protected EnumChatFormatting getColour() {
+ return this.COLOUR;
+ }
+
+ public String formatted() {
+ return this.COLOUR + this.LOOT;
+ }
+
+ public static Quality getRandomQuality() {
+ final int lootChance = MathUtils.randInt(0, 100);
+ if (lootChance <= 10) {
+ return Quality.POOR;
+ } else if (lootChance <= 45) {
+ return Quality.COMMON;
+ } else if (lootChance <= 65) {
+ return Quality.UNCOMMON;
+ } else if (lootChance <= 82) {
+ return Quality.MAGIC;
+ } else if (lootChance <= 92) {
+ return Quality.EPIC;
+ } else if (lootChance <= 97) {
+ return Quality.RARE;
+ } else if (lootChance <= 99) {
+ return Quality.ARTIFACT;
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/helpers/GregtechPlusPlus_API.java b/src/main/java/gtPlusPlus/api/helpers/GregtechPlusPlus_API.java
new file mode 100644
index 0000000000..6fe4209efe
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/helpers/GregtechPlusPlus_API.java
@@ -0,0 +1,203 @@
+package gtPlusPlus.api.helpers;
+
+import java.util.HashMap;
+
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.data.WeightedCollection;
+import gtPlusPlus.api.objects.minecraft.multi.SpecialMultiBehaviour;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy_RTG;
+import gtPlusPlus.xmod.gregtech.api.util.SpecialBehaviourTooltipHandler;
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+
+public class GregtechPlusPlus_API {
+
+ public static class Multiblock_API {
+
+ private static final HashMap<String, SpecialMultiBehaviour> mSpecialBehaviourItemMap = new HashMap<String, SpecialMultiBehaviour>();
+
+ /**
+ * Register a special behaviour for GT++ Multis to listen use.
+ * @param aBehaviour - An Object which has extended {@link SpecialMultiBehaviour}'s base implementation.
+ * @return - Did this behaviour register properly?
+ */
+ public static boolean registerSpecialMultiBehaviour(SpecialMultiBehaviour aBehaviour) {
+ if (aBehaviour.getTriggerItem() == null || aBehaviour.getTriggerItemTooltip() == null || aBehaviour.getTriggerItemTooltip().length() <= 0) {
+ Logger.INFO("Failed to attach custom multiblock logic to "+ItemUtils.getItemName(aBehaviour.getTriggerItem()));
+ return false;
+ }
+ mSpecialBehaviourItemMap.put("UniqueKey_"+aBehaviour.hashCode(), aBehaviour);
+ SpecialBehaviourTooltipHandler.addTooltipForItem(aBehaviour.getTriggerItem(), aBehaviour.getTriggerItemTooltip());
+ Logger.INFO("Attached custom multiblock logic to "+ItemUtils.getItemName(aBehaviour.getTriggerItem()));
+ return true;
+ }
+
+ public static final HashMap<String, SpecialMultiBehaviour> getSpecialBehaviourItemMap() {
+ return mSpecialBehaviourItemMap;
+ }
+
+ /**
+ * Allows RTG Fuel pellets from other mods to be used in the RTG hatch.
+ * @param aStack - The Pellet Stack, sanitsed after passing through.
+ * @param aFuelValue - The Fuel Value of the Pellet to be added to the energy storage.
+ * @return - Did register?
+ */
+ public static boolean registerPelletForRtgHatch(ItemStack aStack, long aFuelValue) {
+ return GT_MetaTileEntity_Hatch_Energy_RTG.registerPelletForHatch(aStack, aFuelValue);
+ }
+
+ }
+
+ public static class VoidMiner_API {
+
+ private static final HashMap<Integer, HashMap<String, WeightedCollection<Block>>> mMinerLootCache;
+
+ static {
+ mMinerLootCache = new HashMap<Integer, HashMap<String, WeightedCollection<Block>>>();
+ }
+
+
+ /**
+ *
+ * Registers an ore block for a dimension. Uses a default weight of 100.
+ * @param aDim - The Dimension ID
+ * @param aOredictName - The OreDict name of the Ore to be mined.
+ * @return - If there was a valid Block found in the OreDict for the provided name.
+ */
+ public static boolean registerOreForVoidMiner(int aDim, String aOredictName) {
+ return registerOreForVoidMiner(aDim, aOredictName, 100);
+ }
+
+ /**
+ *
+ * Registers an ore block for a dimension. Uses a default weight of 100.
+ * @param aDim - The Dimension ID
+ * @param aOredictName - The OreDict name of the Ore to be mined.
+ * @param aWeight - The weight of this ore Block.
+ * @return - If there was a valid Block found in the OreDict for the provided name.
+ */
+ public static boolean registerOreForVoidMiner(int aDim, String aOredictName, int aWeight) {
+ Block b = null;
+ ItemStack[] aValidItems = ItemUtils.validItemsForOreDict(aOredictName);
+ for (ItemStack g : aValidItems) {
+ if (g != null) {
+ b = Block.getBlockFromItem(g.getItem());
+ if (b != null) {
+ break;
+ }
+ }
+ }
+ if (b != null) {
+ registerOreForVoidMiner(aDim, b, aWeight);
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Registers an ore block for a dimension. Uses a default weight of 100.
+ * @param aDim - The Dimension ID
+ * @param aOreBlock - The Ore Block to be mined.
+ */
+ public static void registerOreForVoidMiner(int aDim, Block aOreBlock) {
+ registerOreForVoidMiner(aDim, aOreBlock, 100);
+ }
+
+ /**
+ * Registers an ore block for a dimension.
+ * @param aDim - The Dimension ID
+ * @param aOreBlock - The Ore Block to be mined.
+ * @param aWeight - The weight of this ore Block.
+ */
+ public static void registerOreForVoidMiner(int aDim, Block aOreBlock, int aWeight) {
+ GregtechPlusPlus_API_Internal.writeBlockToDimensionInCache(aDim, 0, aOreBlock, aWeight);
+ }
+
+ /**
+ * Registers a surface block for a dimension. Uses a default weight of 100.
+ * @param aDim - The Dimension ID
+ * @param aDirtBlock - The Dirt/Grass Block to be mined.
+ */
+ public static void registerEarthSurfaceForVoidMiner(int aDim, Block aDirtBlock) {
+ registerEarthSurfaceForVoidMiner(aDim, aDirtBlock, 100);
+ }
+
+ /**
+ * Registers a surface block for a dimension.
+ * @param aDim - The Dimension ID
+ * @param aDirtBlock - The Dirt/Grass Block to be mined.
+ * @param aWeight - The weight of this Dirt/Grass Block.
+ */
+ public static void registerEarthSurfaceForVoidMiner(int aDim, Block aDirtBlock, int aWeight) {
+ GregtechPlusPlus_API_Internal.writeBlockToDimensionInCache(aDim, 0, aDirtBlock, aWeight);
+ }
+
+ /**
+ * Registers a stone block for a dimension. Uses a default weight of 100.
+ * @param aDim - The Dimension ID
+ * @param aStoneBlock - The Stone Block to be mined.
+ */
+ public static void registerEarthStoneForVoidMiner(int aDim, Block aStoneBlock) {
+ registerEarthStoneForVoidMiner(aDim, aStoneBlock, 100);
+ }
+
+ /**
+ * Registers a stone block for a dimension.
+ * @param aDim - The Dimension ID
+ * @param aStoneBlock - The Stone Block to be mined.
+ * @param aWeight - The weight of this Stone Block.
+ */
+ public static void registerEarthStoneForVoidMiner(int aDim, Block aStoneBlock, int aWeight) {
+ GregtechPlusPlus_API_Internal.writeBlockToDimensionInCache(aDim, 0, aStoneBlock, aWeight);
+ }
+
+
+
+
+ public static WeightedCollection<Block> getAllRegisteredOresForDimension(int aDim) {
+ return mMinerLootCache.get(aDim).get("ore");
+ }
+
+ public static WeightedCollection<Block> getAllRegisteredDirtTypesForDimension(int aDim) {
+ return mMinerLootCache.get(aDim).get("dirt");
+ }
+
+ public static WeightedCollection<Block> getAllRegisteredStoneTypesForDimension(int aDim) {
+ return mMinerLootCache.get(aDim).get("stone");
+ }
+
+ public static final HashMap<Integer, HashMap<String, WeightedCollection<Block>>> getVoidMinerLootCache() {
+ return mMinerLootCache;
+ }
+
+ }
+
+
+ private static class GregtechPlusPlus_API_Internal {
+
+ private static void writeBlockToDimensionInCache(int aDim, int aType, Block aBlock, int aWeight) {
+ HashMap<String, WeightedCollection<Block>> aDimMap = VoidMiner_API.mMinerLootCache.get(aDim);
+ if (aDimMap == null) {
+ aDimMap = new HashMap<String, WeightedCollection<Block>>();
+ }
+ WeightedCollection<Block> aMappedBlocks = getBlockMap(aType, aDimMap);
+ aMappedBlocks.put(aWeight, aBlock);
+
+ }
+
+ private static WeightedCollection<Block> getBlockMap(int aType, HashMap<String, WeightedCollection<Block>> aDimMap){
+ WeightedCollection<Block> aMappedBlocks;
+ String aTypeName = ((aType == 0) ? "ore" : (aType == 1) ? "dirt" : (aType == 2) ? "stone" : "error");
+ aMappedBlocks = aDimMap.get(aTypeName);
+ if (aMappedBlocks == null) {
+ aMappedBlocks = new WeightedCollection<Block>();
+ }
+ return aMappedBlocks;
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/helpers/MaterialHelper.java b/src/main/java/gtPlusPlus/api/helpers/MaterialHelper.java
new file mode 100644
index 0000000000..9d2e894d99
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/helpers/MaterialHelper.java
@@ -0,0 +1,76 @@
+package gtPlusPlus.api.helpers;
+
+import net.minecraft.item.ItemStack;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Fluid;
+import gregtech.api.util.GT_OreDictUnificator;
+import gtPlusPlus.core.material.Material;
+import gtPlusPlus.core.recipe.common.CI;
+import gtPlusPlus.core.util.Utils;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+
+public class MaterialHelper {
+
+ public static ItemStack getComponentFromMaterial(OrePrefixes oreprefix, Material material, int amount){
+ return ItemUtils.getOrePrefixStack(oreprefix, material, amount);
+ }
+ public static ItemStack getComponentFromGtMaterial(OrePrefixes oreprefix, Materials material, int amount){
+ return ItemUtils.getGregtechOreStack(oreprefix, material, amount);
+ }
+
+ /**
+ * Generates a 16 Fluid Pipe
+ * @see {@code Example: Copper 16x Pipe (Materials.Copper, Materials.Copper.mName, "Copper", ID, 60, 1000, true)}
+ * @param aMaterial - Pipe Material
+ * @param name - Pipe Internal name
+ * @param displayName - Pipe Display Name
+ * @param aID - Pipe's Meta ID
+ * @param baseCapacity - Pipes Base Capacity
+ * @param heatCapacity - Pipe Max Temp
+ * @param gasProof - Is Gas Proof?
+ * @return A boolean which corresponds to whether or not the Pipe was registered to the Ore Dictionary.
+ */
+ public static boolean generateHexadecuplePipe(Materials aMaterial, String name, String displayName, int aID,
+ int baseCapacity, int heatCapacity, boolean gasProof) {
+ if (Utils.getGregtechVersionAsInt() >= 50930) {
+ try {
+ Class<GT_MetaPipeEntity_Fluid> aPipeEntity = GT_MetaPipeEntity_Fluid.class;
+ Constructor<GT_MetaPipeEntity_Fluid> constructor = aPipeEntity
+ .getConstructor(new Class[] { int.class, String.class, String.class, float.class,
+ Materials.class, int.class, int.class, boolean.class, int.class });
+ if (constructor != null) {
+ GT_MetaPipeEntity_Fluid aPipe;
+ aPipe = constructor.newInstance(aID, "GT_Pipe_" + name + "_Hexadecuple",
+ "Hexadecuple " + displayName + " Fluid Pipe", 1.0F, aMaterial, baseCapacity, heatCapacity,
+ gasProof, 16);
+ return GT_OreDictUnificator.registerOre("pipeHexadecuple" + aMaterial, aPipe.getStackForm(1L));
+ }
+
+ } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
+ | IllegalArgumentException | InvocationTargetException e) {
+ }
+ }
+ return false;
+ }
+
+ public static ItemStack getCells(Materials aMaterial, int i) {
+ return ItemUtils.getOrePrefixStack(OrePrefixes.cell, aMaterial, i);
+ }
+ public static ItemStack getDust(Materials aMaterial, int i) {
+ return ItemUtils.getOrePrefixStack(OrePrefixes.dust, aMaterial, i);
+ }
+ public static ItemStack getDustSmall(Materials aMaterial, int i) {
+ return ItemUtils.getOrePrefixStack(OrePrefixes.dustSmall, aMaterial, i);
+ }
+ public static ItemStack getDustTiny(Materials aMaterial, int i) {
+ return ItemUtils.getOrePrefixStack(OrePrefixes.dustTiny, aMaterial, i);
+ }
+ public static ItemStack getGems(Materials aMaterial, int i) {
+ return ItemUtils.getOrePrefixStack(OrePrefixes.gem, aMaterial, i);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/IChunkLoader.java b/src/main/java/gtPlusPlus/api/interfaces/IChunkLoader.java
new file mode 100644
index 0000000000..c04e25f570
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/IChunkLoader.java
@@ -0,0 +1,33 @@
+package gtPlusPlus.api.interfaces;
+
+import java.util.Set;
+
+import net.minecraft.world.ChunkCoordIntPair;
+
+public interface IChunkLoader {
+
+ public long getTicksRemaining();
+
+ public void setTicksRemaining(long aTicks);
+
+ public ChunkCoordIntPair getResidingChunk();
+
+ public void setResidingChunk(ChunkCoordIntPair aCurrentChunk);
+
+ public boolean getChunkLoadingActive();
+
+ public void setChunkLoadingActive(boolean aActive);
+
+ public boolean getDoesWorkChunkNeedReload();
+
+ public void setDoesWorkChunkNeedReload(boolean aActive);
+
+ public boolean addChunkToLoadedList(ChunkCoordIntPair aActiveChunk);
+
+ public boolean removeChunkFromLoadedList(ChunkCoordIntPair aActiveChunk);
+
+ public Set<ChunkCoordIntPair> getManagedChunks();
+
+ public int getChunkloaderTier();
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/IComparableRecipe.java b/src/main/java/gtPlusPlus/api/interfaces/IComparableRecipe.java
new file mode 100644
index 0000000000..ddbf9f38bb
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/IComparableRecipe.java
@@ -0,0 +1,8 @@
+package gtPlusPlus.api.interfaces;
+
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GTPP_Recipe;
+
+public interface IComparableRecipe extends Comparable<GT_Recipe>{
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/IEntityCatcher.java b/src/main/java/gtPlusPlus/api/interfaces/IEntityCatcher.java
new file mode 100644
index 0000000000..5ab90d47ce
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/IEntityCatcher.java
@@ -0,0 +1,21 @@
+package gtPlusPlus.api.interfaces;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
+
+import gtPlusPlus.api.objects.minecraft.BlockPos;
+
+public interface IEntityCatcher {
+
+ public boolean hasEntity(ItemStack aStack);
+
+ public Entity getStoredEntity(World aWorld, ItemStack aStack);
+
+ public boolean setStoredEntity(World aWorld, ItemStack aStack, Entity aEntity);
+
+ public Class<? extends Entity> getStoredEntityClass(ItemStack aStack);
+
+ public boolean spawnStoredEntity(World aWorld, ItemStack aStack, BlockPos aPos);
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/IGeneratorWorld.java b/src/main/java/gtPlusPlus/api/interfaces/IGeneratorWorld.java
new file mode 100644
index 0000000000..63f2adbba7
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/IGeneratorWorld.java
@@ -0,0 +1,17 @@
+package gtPlusPlus.api.interfaces;
+
+import java.util.Random;
+import net.minecraft.world.World;
+
+public abstract interface IGeneratorWorld
+{
+ public abstract boolean generate(World paramWorld, Random paramRandom, int paramInt1, int paramInt2);
+
+ public abstract void initiate();
+
+ public abstract int getExtentX();
+
+ public abstract int getExtentZ();
+
+ public abstract int getRange();
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/IGregtechPacketEntity.java b/src/main/java/gtPlusPlus/api/interfaces/IGregtechPacketEntity.java
new file mode 100644
index 0000000000..fa59c58d9f
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/IGregtechPacketEntity.java
@@ -0,0 +1,13 @@
+package gtPlusPlus.api.interfaces;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public interface IGregtechPacketEntity {
+
+ public void writePacketData(DataOutputStream data) throws IOException;
+
+ public void readPacketData(DataInputStream data) throws IOException;
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/IGregtechPower.java b/src/main/java/gtPlusPlus/api/interfaces/IGregtechPower.java
new file mode 100644
index 0000000000..4bb29b3354
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/IGregtechPower.java
@@ -0,0 +1,145 @@
+package gtPlusPlus.api.interfaces;
+
+import net.minecraft.block.Block;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+
+import gregtech.api.interfaces.IDescribable;
+import gregtech.api.interfaces.tileentity.*;
+
+public abstract interface IGregtechPower extends IGearEnergyTileEntity, ITurnable, IGregTechDeviceInformation, IDescribable, IBasicEnergyContainer {
+
+ @Override
+ public String[] getDescription();
+
+ @Override
+ default boolean isUniversalEnergyStored(long p0) {
+ return false;
+ }
+
+ @Override
+ public long getOutputAmperage();
+
+ @Override
+ public long getOutputVoltage();
+
+ @Override
+ public long getInputAmperage();
+
+ @Override
+ public long getInputVoltage();
+
+ @Override
+ public boolean decreaseStoredEnergyUnits(long p0, boolean p1);
+
+ @Override
+ public boolean increaseStoredEnergyUnits(long p0, boolean p1);
+
+ @Override
+ public boolean drainEnergyUnits(byte p0, long p1, long p2);
+
+ @Override
+ public long getAverageElectricInput();
+
+ @Override
+ public long getAverageElectricOutput();
+
+ @Override
+ public long getStoredEU();
+
+ @Override
+ public long getEUCapacity();
+
+ @Override
+ public long getStoredSteam();
+
+ @Override
+ public long getSteamCapacity();
+
+ @Override
+ public boolean increaseStoredSteam(long p0, boolean p1);
+
+ @Override
+ public Block getBlockAtSide(byte p0);
+
+ @Override
+ public Block getBlockAtSideAndDistance(byte p0, int p1);
+
+ @Override
+ public Block getBlockOffset(int p0, int p1, int p2);
+
+
+ @Override
+ public TileEntity getTileEntity(int p0, int p1, int p2);
+
+ @Override
+ public TileEntity getTileEntityAtSide(byte p0);
+
+ @Override
+ public TileEntity getTileEntityAtSideAndDistance(byte p0, int p1);
+
+ @Override
+ public TileEntity getTileEntityOffset(int p0, int p1, int p2);
+
+ @Override
+ public World getWorld();
+
+ @Override
+ public int getXCoord();
+
+ @Override
+ public short getYCoord();
+
+ @Override
+ public int getZCoord();
+
+ @Override
+ public boolean isClientSide();
+
+ @Override
+ public boolean isDead();
+
+ @Override
+ public boolean isInvalidTileEntity();
+
+ @Override
+ public boolean isServerSide();
+
+ @Override
+ public void readFromNBT(NBTTagCompound p0);
+
+ @Override
+ public void writeToNBT(NBTTagCompound p0);
+
+ @Override
+ public boolean acceptsRotationalEnergy(byte p0);
+
+ @Override
+ public boolean injectRotationalEnergy(byte p0, long p1, long p2);
+
+ @Override
+ public long injectEnergyUnits(byte p0, long p1, long p2);
+
+ @Override
+ public boolean inputEnergyFrom(byte p0);
+
+ @Override
+ public boolean outputsEnergyTo(byte p0);
+
+ @Override
+ public String[] getInfoData();
+
+ @Override
+ default public boolean isGivingInformation() {
+ return true;
+ }
+
+/* boolean onPreTick(TilePoweredGT tilePoweredGT, long mTickTimer2);
+
+ boolean onTick(TilePoweredGT iGregTechTileEntity, long mTickTimer2);
+
+ boolean onPostTick(TilePoweredGT iGregTechTileEntity, long mTickTimer2);*/
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/ILazyCoverable.java b/src/main/java/gtPlusPlus/api/interfaces/ILazyCoverable.java
new file mode 100644
index 0000000000..9e1a7431db
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/ILazyCoverable.java
@@ -0,0 +1,144 @@
+package gtPlusPlus.api.interfaces;
+
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+public interface ILazyCoverable extends ICoverable {
+
+ @Override
+ default byte getColorization() {
+ return 0;
+ }
+
+ @Override
+ default byte setColorization(byte arg0) {
+ return 0;
+ }
+
+ @Override
+ default byte getInputRedstoneSignal(byte arg0) {
+ return 0;
+ }
+
+ @Override
+ default byte getStrongestRedstone() {
+ return 0;
+ }
+
+ @Override
+ default boolean getRedstone() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ default boolean getRedstone(byte arg0) {
+ return false;
+ }
+
+ @Override
+ default boolean isUniversalEnergyStored(long arg0) {
+ return false;
+ }
+
+ @Override
+ default long getUniversalEnergyStored() {
+ return 0;
+ }
+
+ @Override
+ default long getUniversalEnergyCapacity() {
+ return 0;
+ }
+
+ @Override
+ default long getStoredSteam() {
+ return 0;
+ }
+
+ @Override
+ default long getSteamCapacity() {
+ return 0;
+ }
+
+ @Override
+ default boolean increaseStoredSteam(long arg0, boolean arg2) {
+ return false;
+ }
+
+ @Override
+ default byte getOutputRedstoneSignal(byte arg0) {
+ return 0;
+ }
+
+ @Override
+ default void setOutputRedstoneSignal(byte arg0, byte arg1) {
+
+ }
+
+ @Override
+ default byte getStrongOutputRedstoneSignal(byte arg0) {
+ return 0;
+ }
+
+ @Override
+ default void setStrongOutputRedstoneSignal(byte arg0, byte arg1) {
+
+ }
+
+ @Override
+ default byte getComparatorValue(byte arg0) {
+ return 0;
+ }
+
+ @Override
+ default IGregTechTileEntity getIGregTechTileEntity(int arg0, int arg1, int arg2) {
+ return null;
+ }
+
+ @Override
+ default IGregTechTileEntity getIGregTechTileEntityOffset(int arg0, int arg1, int arg2) {
+ return null;
+ }
+
+ @Override
+ default IGregTechTileEntity getIGregTechTileEntityAtSide(byte arg0) {
+ return null;
+ }
+
+ @Override
+ default IGregTechTileEntity getIGregTechTileEntityAtSideAndDistance(byte arg0, int arg1) {
+ return null;
+ }
+
+ @Override
+ default byte getMetaID(int arg0, int arg1, int arg2) {
+ return 0;
+ }
+
+ @Override
+ default byte getMetaIDOffset(int arg0, int arg1, int arg2) {
+ return 0;
+ }
+
+ @Override
+ default byte getMetaIDAtSide(byte arg0) {
+ return 0;
+ }
+
+ @Override
+ default byte getMetaIDAtSideAndDistance(byte arg0, int arg1) {
+ return 0;
+ }
+
+ @Override
+ default boolean isDead() {
+ return false;
+ }
+
+ @Override
+ default void setLightValue(byte arg0) {
+
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/IPlugin.java b/src/main/java/gtPlusPlus/api/interfaces/IPlugin.java
new file mode 100644
index 0000000000..67be182402
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/IPlugin.java
@@ -0,0 +1,40 @@
+package gtPlusPlus.api.interfaces;
+
+import gtPlusPlus.api.objects.Logger;
+
+public interface IPlugin {
+
+ /**
+ * @return A {@link String} object which returns the {@link IPlugin}'s name.
+ */
+ public String getPluginName();
+
+ /**
+ * @return
+ * A {@link String} object which returns the {@link IPlugin}'s short name.
+ * This String should only contain 4 Characters.
+ */
+ public String getPluginAbbreviation();
+
+ /**
+ * @param message - A {@link String} object which holds a message to be logged to console.
+ */
+ default void log(String message) {
+ Logger.INFO("["+getPluginAbbreviation()+"] "+message);
+ }
+
+ /**
+ * @param message - A {@link String} object which holds a warning/error message to be logged to console.
+ */
+ default void logDebug(String message) {
+ Logger.WARNING("["+getPluginAbbreviation()+"] "+message);
+ }
+
+ public boolean preInit();
+ public boolean init();
+ public boolean postInit();
+
+ public boolean serverStart();
+ public boolean serverStop();
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/IRandomGenerator.java b/src/main/java/gtPlusPlus/api/interfaces/IRandomGenerator.java
new file mode 100644
index 0000000000..233fb93d4d
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/IRandomGenerator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005, Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of the modp.com nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This is the standard "new" BSD license:
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+
+package gtPlusPlus.api.interfaces;
+
+/**
+ * Simplified interface for random number generation
+ *
+ * @author Nick Galbreath -- nickg [at] modp [dot] com
+ * @version 1 -- 06-Jul-2005
+ */
+public interface IRandomGenerator {
+
+ /**
+ * Returns N random bits
+ *
+ * See also java.util.Random#next
+ * @param numBits
+ * @return and int with the LSB being random
+ */
+ public int next(int numBits);
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/ITexturedBlock.java b/src/main/java/gtPlusPlus/api/interfaces/ITexturedBlock.java
new file mode 100644
index 0000000000..47e692bffb
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/ITexturedBlock.java
@@ -0,0 +1,14 @@
+package gtPlusPlus.api.interfaces;
+
+import net.minecraft.block.Block;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ITexturedTileEntity;
+
+public interface ITexturedBlock extends ITexturedTileEntity{
+
+ ITexture[] getTexture(byte side);
+
+ ITexture[] getTexture(Block block, byte side);
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/ITileTooltip.java b/src/main/java/gtPlusPlus/api/interfaces/ITileTooltip.java
new file mode 100644
index 0000000000..08866c2712
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/ITileTooltip.java
@@ -0,0 +1,7 @@
+package gtPlusPlus.api.interfaces;
+
+public interface ITileTooltip {
+
+ public abstract int getTooltipID();
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/IToolable.java b/src/main/java/gtPlusPlus/api/interfaces/IToolable.java
new file mode 100644
index 0000000000..24797825a9
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/IToolable.java
@@ -0,0 +1,17 @@
+package gtPlusPlus.api.interfaces;
+
+public interface IToolable {
+
+ public boolean isScrewdriverable();
+ public boolean onScrewdriverLMB();
+ public boolean onScrewdriverRMB();
+
+ public boolean isWrenchable();
+ public boolean onWrenchLMB();
+ public boolean onWrenchRMB();
+
+ public boolean isMalletable();
+ public boolean onMalletLMB();
+ public boolean onMalletRMB();
+
+}
diff --git a/src/main/java/gtPlusPlus/api/interfaces/RunnableWithInfo.java b/src/main/java/gtPlusPlus/api/interfaces/RunnableWithInfo.java
new file mode 100644
index 0000000000..4f4b9d7acd
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/interfaces/RunnableWithInfo.java
@@ -0,0 +1,12 @@
+package gtPlusPlus.api.interfaces;
+
+public interface RunnableWithInfo<V> extends Runnable {
+
+ public V getInfoData();
+
+ default public Class<?> getInfoDataType() {
+ return getInfoData().getClass();
+ }
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/GregtechException.java b/src/main/java/gtPlusPlus/api/objects/GregtechException.java
new file mode 100644
index 0000000000..916dbc4aaf
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/GregtechException.java
@@ -0,0 +1,28 @@
+package gtPlusPlus.api.objects;
+
+public class GregtechException extends Throwable {
+
+ private static final long serialVersionUID = 3601884582161841486L;
+
+ public GregtechException(String aError) {
+ this(aError, true);
+ }
+
+ public GregtechException(String aError, boolean aIsVerbose) {
+ Logger.ERROR("Throwing GT++ Exception!");
+ Logger.ERROR("[EXCEPTION] "+aError);
+ if (aIsVerbose) {
+ Logger.INFO("Throwing GT++ Exception!");
+ Logger.INFO("[EXCEPTION] "+aError);
+ printStackTrace();
+ }
+ }
+
+ @Override
+ public void printStackTrace() {
+ super.printStackTrace();
+ }
+
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/Logger.java b/src/main/java/gtPlusPlus/api/objects/Logger.java
new file mode 100644
index 0000000000..1a1da6868b
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/Logger.java
@@ -0,0 +1,179 @@
+package gtPlusPlus.api.objects;
+
+import cpw.mods.fml.common.FMLLog;
+import cpw.mods.fml.relauncher.FMLRelaunchLog;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.preloader.CORE_Preloader;
+import gtPlusPlus.preloader.asm.AsmConfig;
+import org.apache.logging.log4j.LogManager;
+
+public class Logger {
+
+ public Logger(String string) {
+
+ }
+
+ // Logging Functions
+ public static final org.apache.logging.log4j.Logger modLogger = Logger.makeLogger();
+
+ // Generate GT++ Logger
+ public static org.apache.logging.log4j.Logger makeLogger() {
+ final org.apache.logging.log4j.Logger gtPlusPlusLogger = LogManager.getLogger("GT++");
+ return gtPlusPlusLogger;
+ }
+
+ private static final boolean enabled = !AsmConfig.disableAllLogging;
+
+ public static final org.apache.logging.log4j.Logger getLogger() {
+ return modLogger;
+ }
+
+ // Non-Dev Comments
+ public static void INFO(final String s) {
+ if (enabled) {
+ modLogger.info(s);
+ }
+ }
+
+ // Non-Dev Comments
+ public static void MACHINE_INFO(String s, Object... args) {
+ if (enabled) {
+ boolean localPlayer = CORE_Preloader.DEV_ENVIRONMENT;
+ if (CORE.ConfigSwitches.MACHINE_INFO || localPlayer) {
+ final String name1 = gtPlusPlus.core.util.reflect.ReflectionUtils.getMethodName(2);
+ modLogger.info("Machine Info: " + s + " | " + name1, args);
+ }
+ }
+ }
+
+ // Developer Comments
+ public static void WARNING(final String s) {
+ if (enabled) {
+ if (CORE_Preloader.DEBUG_MODE) {
+ modLogger.warn(s);
+ }
+ }
+ }
+
+ // Errors
+ public static void ERROR(final String s) {
+ if (enabled) {
+ if (CORE_Preloader.DEBUG_MODE) {
+ modLogger.fatal(s);
+ }
+ }
+ }
+
+ // Developer Logger
+ public static void SPECIFIC_WARNING(final String whatToLog, final String msg, final int line) {
+ if (enabled) {
+ // if (!CORE_Preloader.DEBUG_MODE){
+ FMLLog.warning("GT++ |" + line + "| " + whatToLog + " | " + msg);
+ // }
+ }
+ }
+
+ // ASM Comments
+ public static void LOG_ASM(final String s) {
+ if (enabled) {
+ FMLRelaunchLog.info("[Special ASM Logging] ", s);
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+ /**
+ * Special Loggers
+ */
+
+ /**
+ * Special Logger for Bee related content
+ */
+ public static void BEES(final String s) {
+ if (enabled) {
+ if (CORE_Preloader.DEV_ENVIRONMENT || CORE_Preloader.DEBUG_MODE) {
+ modLogger.info("[Bees] "+s);
+ }
+ }
+ }
+ /**
+ * Special Logger for Debugging Bee related content
+ */
+ public static void DEBUG_BEES(final String s) {
+ if (enabled) {
+ if (CORE_Preloader.DEV_ENVIRONMENT || CORE_Preloader.DEBUG_MODE) {
+ modLogger.info("[Debug][Bees] "+s);
+ }
+ }
+ }
+
+
+
+ /**
+ * Special Logger for Materials related content
+ */
+ public static void MATERIALS(final String s) {
+ if (enabled) {
+ if (CORE_Preloader.DEV_ENVIRONMENT || CORE_Preloader.DEBUG_MODE) {
+ modLogger.info("[Materials] "+s);
+ }
+ }
+ }
+ /**
+ * Special Logger for Debugging Materials related content
+ */
+ public static void DEBUG_MATERIALS(final String s) {
+ if (enabled) {
+ if (CORE_Preloader.DEV_ENVIRONMENT || CORE_Preloader.DEBUG_MODE) {
+ modLogger.info("[Debug][Materials] "+s);
+ }
+ }
+ }
+
+ /**
+ * Special Logger for Reflection related content
+ */
+ public static void REFLECTION(final String s) {
+ if (enabled) {
+ if (CORE_Preloader.DEV_ENVIRONMENT || CORE_Preloader.DEBUG_MODE) {
+ modLogger.info("[Reflection] "+s);
+ }
+ }
+ }
+
+
+ /**
+ * Special Logger for Darkworld related content
+ */
+ public static void WORLD(final String s) {
+ if (enabled) {
+ if (CORE_Preloader.DEV_ENVIRONMENT || CORE_Preloader.DEBUG_MODE) {
+ modLogger.info("[WorldGen] "+s);
+ }
+ }
+ }
+
+ public static void RECIPE(String string) {
+ if (enabled) {
+ if (/*CORE_Preloader.DEV_ENVIRONMENT || */CORE_Preloader.DEBUG_MODE) {
+ modLogger.info("[Recipe] "+string);
+ }
+ }
+ }
+
+ public static void SPACE(final String s) {
+ if (enabled) {
+ modLogger.info("[Space] "+s);
+ }
+ }
+
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/data/AutoMap.java b/src/main/java/gtPlusPlus/api/objects/data/AutoMap.java
new file mode 100644
index 0000000000..e04f1af03a
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/AutoMap.java
@@ -0,0 +1,345 @@
+package gtPlusPlus.api.objects.data;
+
+import java.io.Serializable;
+import java.util.*;
+
+public class AutoMap<V> implements Iterable<V>, Cloneable, Serializable, Collection<V>, Queue<V>, List<V> {
+
+ /**
+ * The Internal Map
+ */
+ protected final Map<Integer, V> mInternalMap;
+ protected final Map<String, Integer> mInternalNameMap;
+
+ /**
+ * The Internal ID
+ */
+ private int mInternalID = 0;
+ private static final long serialVersionUID = 3771412318075131790L;
+
+
+ public AutoMap() {
+ this(new LinkedHashMap<Integer, V>());
+ }
+
+ public Map<Integer, V> getMap(){
+ return mInternalMap;
+ }
+
+ public AutoMap(Map<Integer, V> defaultMapType) {
+ mInternalMap = defaultMapType;
+ mInternalNameMap = new LinkedHashMap<String, Integer>();
+ }
+
+ /**
+ * Generates an AutoMap from the List.
+ * @param aList - Data to be inserted into the AutoMap.
+ */
+ public AutoMap(List<V> aList) {
+ mInternalMap = new LinkedHashMap<Integer, V>();
+ mInternalNameMap = new LinkedHashMap<String, Integer>();
+ if (aList != null && aList.size() > 0) {
+ for (V obj : aList) {
+ add(obj);
+ }
+ }
+ }
+ /**
+ * Generates an AutoMap from a Set.
+ * @param aList - Data to be inserted into the AutoMap.
+ */
+ public AutoMap(Set<V> aList) {
+ mInternalMap = new LinkedHashMap<Integer, V>();
+ mInternalNameMap = new LinkedHashMap<String, Integer>();
+ if (aList != null && aList.size() > 0) {
+ for (V obj : aList) {
+ add(obj);
+ }
+ }
+ }
+ /**
+ * Generates an AutoMap from a Collection.
+ * @param aList - Data to be inserted into the AutoMap.
+ */
+ public AutoMap(Collection<V> aList) {
+ mInternalMap = new LinkedHashMap<Integer, V>();
+ mInternalNameMap = new LinkedHashMap<String, Integer>();
+ if (aList != null && aList.size() > 0) {
+ for (V obj : aList) {
+ add(obj);
+ }
+ }
+ }
+
+ /**
+ * Generates an AutoMap from a Array.
+ * @param aArray - Data to be inserted into the AutoMap.
+ */
+ public AutoMap(V[] aArray) {
+ mInternalMap = new LinkedHashMap<Integer, V>();
+ mInternalNameMap = new LinkedHashMap<String, Integer>();
+ if (aArray != null && aArray.length > 0) {
+ for (V obj : aArray) {
+ add(obj);
+ }
+ }
+ }
+
+ @Override
+ public Iterator<V> iterator() {
+ return values().iterator();
+ }
+
+ public synchronized boolean setValue(V object){
+ int mOriginalID = this.mInternalID;
+ put(object);
+ if (this.mInternalMap.get(mOriginalID).equals(object) || mOriginalID > this.mInternalID){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ public synchronized V put(V object){
+ return set(object);
+ }
+
+ public synchronized boolean add(V object){
+ return set(object) != null;
+ }
+
+ public synchronized V set(V object){
+ if (object == null) {
+ return null;
+ }
+ mInternalNameMap.put(""+object.hashCode(), (mInternalID+1));
+ return mInternalMap.put(mInternalID++, object);
+ }
+
+ public synchronized V get(int id){
+ return mInternalMap.get(id);
+ }
+
+ public synchronized Collection<V> values(){
+ return mInternalMap.values();
+ }
+
+ public synchronized int size(){
+ return mInternalMap.size();
+ }
+
+ public synchronized int hashCode(){
+ return mInternalMap.hashCode();
+ }
+
+ public synchronized boolean containsKey(int key){
+ return mInternalMap.containsKey(key);
+ }
+
+ public synchronized boolean containsValue(V value){
+ return mInternalMap.containsValue(value);
+ }
+
+ public synchronized boolean isEmpty(){
+ return mInternalMap.isEmpty();
+ }
+
+ public synchronized void clear(){
+ this.mInternalID = 0;
+ this.mInternalMap.clear();
+ this.mInternalNameMap.clear();
+ return;
+ }
+
+ @SuppressWarnings("unchecked")
+ public V[] toArray() {
+ V[] toR = (V[]) java.lang.reflect.Array.newInstance(mInternalMap.get(0).getClass(), mInternalMap.size());
+ for (int i = 0; i < mInternalMap.size(); i++) {
+ toR[i] = mInternalMap.get(i);
+ }
+ return toR;
+ }
+
+ public synchronized final int getInternalID() {
+ return mInternalID;
+ }
+
+ public synchronized final boolean remove(Object value) {
+ value.getClass();
+ if (this.mInternalMap.containsValue(value)) {
+ return this.mInternalMap.remove(mInternalNameMap.get(""+value.hashCode()), value);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ for (V g : this.mInternalMap.values()) {
+ if (g.equals(o)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <V> V[] toArray(V[] a) {
+ return (V[]) toArray();
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ boolean aTrue = true;
+ for (Object g : c) {
+ if (!this.contains(g)) {
+ aTrue = false;
+ }
+ }
+ return aTrue;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends V> c) {
+ boolean aTrue = true;
+ for (V g : c) {
+ if (!this.add(g)) {
+ aTrue = false;
+ }
+ }
+ return aTrue;
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ boolean aTrue = true;
+ for (Object g : c) {
+ if (!this.remove(g)) {
+ aTrue = false;
+ }
+ }
+ return aTrue;
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ AutoMap<?> aTempAllocation = new AutoMap<Object>();
+ boolean aTrue = false;
+ aTempAllocation = this;
+ aTempAllocation.removeAll(c);
+ aTempAllocation.clear();
+ aTrue = aTempAllocation.isEmpty();
+ aTempAllocation.clear();
+ return aTrue;
+ }
+
+ @Override
+ public boolean offer(V e) {
+ return add(e);
+ }
+
+ @Override
+ public V remove() {
+ V y = this.get(0);
+ if (remove(y))
+ return y;
+ else
+ return null;
+ }
+
+ @Override
+ public V poll() {
+ if (this.mInternalMap.isEmpty()) {
+ return null;
+ }
+ return remove();
+ }
+
+ @Override
+ public V element() {
+ if (this.mInternalMap.isEmpty()) {
+ return null;
+ }
+ return this.get(0);
+ }
+
+ @Override
+ public V peek() {
+ return element();
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends V> c) {
+ for (V y : c) {
+ add(y);
+ }
+ return true;
+ }
+
+ @Override
+ public V set(int index, V element) {
+ return mInternalMap.put(index, element);
+ }
+
+ @Override
+ public void add(int index, V element) {
+ add(element);
+ }
+
+ @Override
+ public V remove(int index) {
+ V h = mInternalMap.get(index);
+ set(index, null);
+ return h;
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ int aCount = 0;
+ for (V of : mInternalMap.values()) {
+ if (of != o) {
+ aCount++;
+ continue;
+ }
+ else {
+ return aCount;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ //TODO
+ return indexOf(o);
+ }
+
+ @Override
+ public ListIterator<V> listIterator() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ListIterator<V> listIterator(int index) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public List<V> subList(int fromIndex, int toIndex) {
+ AutoMap<V> aNewSubList = new AutoMap<V>();
+ for (int slot=fromIndex; slot<=toIndex; slot++) {
+ V obj = mInternalMap.get(slot);
+ if (obj == null) {
+ continue;
+ }
+ else {
+ aNewSubList.put(obj);
+ }
+ }
+ return aNewSubList;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/data/ConcurrentHashSet.java b/src/main/java/gtPlusPlus/api/objects/data/ConcurrentHashSet.java
new file mode 100644
index 0000000000..991908e402
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/ConcurrentHashSet.java
@@ -0,0 +1,18 @@
+package gtPlusPlus.api.objects.data;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class ConcurrentHashSet<V> extends ConcurrentSet<V> {
+
+ private static final long serialVersionUID = -1293478938482781728L;
+
+ public ConcurrentHashSet() {
+ this(new ConcurrentHashMap<Integer, V>());
+ }
+
+ public ConcurrentHashSet(ConcurrentMap<Integer, V> defaultMapType) {
+ super(defaultMapType);
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/data/ConcurrentSet.java b/src/main/java/gtPlusPlus/api/objects/data/ConcurrentSet.java
new file mode 100644
index 0000000000..1d3ffc1c01
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/ConcurrentSet.java
@@ -0,0 +1,53 @@
+package gtPlusPlus.api.objects.data;
+
+import java.io.Serializable;
+import java.util.AbstractSet;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentMap;
+
+public abstract class ConcurrentSet<E> extends AbstractSet<E> implements Serializable {
+
+ private static final long serialVersionUID = -6761513279741915432L;
+
+ private final ConcurrentMap<Integer, E> mInternalMap;
+
+ private int mInternalID = 0;
+
+ /**
+ * Creates a new instance which wraps the specified {@code map}.
+ */
+ public ConcurrentSet(ConcurrentMap<Integer, E> aMap) {
+ mInternalMap = aMap;
+ }
+
+ @Override
+ public int size() {
+ return mInternalMap.size();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return mInternalMap.containsKey(o);
+ }
+
+ @Override
+ public boolean add(E o) {
+ return mInternalMap.putIfAbsent(mInternalID++, o) == null;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ return mInternalMap.remove(o) != null;
+ }
+
+ @Override
+ public void clear() {
+ this.mInternalID = 0;
+ mInternalMap.clear();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return mInternalMap.values().iterator();
+ }
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/data/FlexiblePair.java b/src/main/java/gtPlusPlus/api/objects/data/FlexiblePair.java
new file mode 100644
index 0000000000..64f57b4e5a
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/FlexiblePair.java
@@ -0,0 +1,39 @@
+package gtPlusPlus.api.objects.data;
+
+import java.io.Serializable;
+
+import com.google.common.base.Objects;
+
+public class FlexiblePair<K,V> implements Serializable {
+
+ /**
+ * SVUID
+ */
+ private static final long serialVersionUID = 1250550491092812443L;
+ private final K key;
+ private V value;
+
+ public FlexiblePair(final K key, final V value){
+ this.key = key;
+ this.value = value;
+ }
+
+ final public K getKey(){
+ return this.key;
+ }
+
+ final public V getValue(){
+ return this.value;
+ }
+
+ final public void setValue(V aObj) {
+ value = aObj;
+ }
+
+ @Override
+ public int hashCode() {
+ Integer aCode = Objects.hashCode(getKey(), getValue());
+ return aCode != null ? aCode : super.hashCode();
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/objects/data/ObjMap.java b/src/main/java/gtPlusPlus/api/objects/data/ObjMap.java
new file mode 100644
index 0000000000..49dd70d2b8
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/ObjMap.java
@@ -0,0 +1,285 @@
+package gtPlusPlus.api.objects.data;
+
+import java.util.Arrays;
+
+/**
+ * Object-2-object map based on IntIntMap4a
+ */
+public class ObjMap<K, V>
+{
+ private static final Object FREE_KEY = new Object();
+ private static final Object REMOVED_KEY = new Object();
+
+ /** Keys and values */
+ private Object[] m_data;
+
+ /** Value for the null key (if inserted into a map) */
+ private Object m_nullValue;
+ private boolean m_hasNull;
+
+ /** Fill factor, must be between (0 and 1) */
+ private final float m_fillFactor;
+ /** We will resize a map once it reaches this size */
+ private int m_threshold;
+ /** Current map size */
+ private int m_size;
+ /** Mask to calculate the original position */
+ private int m_mask;
+ /** Mask to wrap the actual array pointer */
+ private int m_mask2;
+
+ public ObjMap( final int size, final float fillFactor )
+ {
+ if ( fillFactor <= 0 || fillFactor >= 1 )
+ throw new IllegalArgumentException( "FillFactor must be in (0, 1)" );
+ if ( size <= 0 )
+ throw new IllegalArgumentException( "Size must be positive!" );
+ final int capacity = arraySize(size, fillFactor);
+ m_mask = capacity - 1;
+ m_mask2 = capacity * 2 - 1;
+ m_fillFactor = fillFactor;
+
+ m_data = new Object[capacity * 2];
+ Arrays.fill( m_data, FREE_KEY );
+
+ m_threshold = (int) (capacity * fillFactor);
+ }
+
+ @SuppressWarnings("unchecked")
+ public V get( final K key )
+ {
+ if ( key == null )
+ return (V) m_nullValue; //we null it on remove, so safe not to check a flag here
+
+ int ptr = (key.hashCode() & m_mask) << 1;
+ Object k = m_data[ ptr ];
+
+ if ( k == FREE_KEY )
+ return null; //end of chain already
+ if ( k.equals( key ) ) //we check FREE and REMOVED prior to this call
+ return (V) m_data[ ptr + 1 ];
+ while ( true )
+ {
+ ptr = (ptr + 2) & m_mask2; //that's next index
+ k = m_data[ ptr ];
+ if ( k == FREE_KEY )
+ return null;
+ if ( k.equals( key ) )
+ return (V) m_data[ ptr + 1 ];
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public V put( final K key, final V value )
+ {
+ if ( key == null )
+ return insertNullKey(value);
+
+ int ptr = getStartIndex(key) << 1;
+ Object k = m_data[ptr];
+
+ if ( k == FREE_KEY ) //end of chain already
+ {
+ m_data[ ptr ] = key;
+ m_data[ ptr + 1 ] = value;
+ if ( m_size >= m_threshold )
+ rehash( m_data.length * 2 ); //size is set inside
+ else
+ ++m_size;
+ return null;
+ }
+ else if ( k.equals( key ) ) //we check FREE and REMOVED prior to this call
+ {
+ final Object ret = m_data[ ptr + 1 ];
+ m_data[ ptr + 1 ] = value;
+ return (V) ret;
+ }
+
+ int firstRemoved = -1;
+ if ( k == REMOVED_KEY )
+ firstRemoved = ptr; //we may find a key later
+
+ while ( true )
+ {
+ ptr = ( ptr + 2 ) & m_mask2; //that's next index calculation
+ k = m_data[ ptr ];
+ if ( k == FREE_KEY )
+ {
+ if ( firstRemoved != -1 )
+ ptr = firstRemoved;
+ m_data[ ptr ] = key;
+ m_data[ ptr + 1 ] = value;
+ if ( m_size >= m_threshold )
+ rehash( m_data.length * 2 ); //size is set inside
+ else
+ ++m_size;
+ return null;
+ }
+ else if ( k.equals( key ) )
+ {
+ final Object ret = m_data[ ptr + 1 ];
+ m_data[ ptr + 1 ] = value;
+ return (V) ret;
+ }
+ else if ( k == REMOVED_KEY )
+ {
+ if ( firstRemoved == -1 )
+ firstRemoved = ptr;
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public V remove( final K key )
+ {
+ if ( key == null )
+ return removeNullKey();
+
+ int ptr = getStartIndex(key) << 1;
+ Object k = m_data[ ptr ];
+ if ( k == FREE_KEY )
+ return null; //end of chain already
+ else if ( k.equals( key ) ) //we check FREE and REMOVED prior to this call
+ {
+ --m_size;
+ if ( m_data[ ( ptr + 2 ) & m_mask2 ] == FREE_KEY )
+ m_data[ ptr ] = FREE_KEY;
+ else
+ m_data[ ptr ] = REMOVED_KEY;
+ final V ret = (V) m_data[ ptr + 1 ];
+ m_data[ ptr + 1 ] = null;
+ return ret;
+ }
+ while ( true )
+ {
+ ptr = ( ptr + 2 ) & m_mask2; //that's next index calculation
+ k = m_data[ ptr ];
+ if ( k == FREE_KEY )
+ return null;
+ else if ( k.equals( key ) )
+ {
+ --m_size;
+ if ( m_data[ ( ptr + 2 ) & m_mask2 ] == FREE_KEY )
+ m_data[ ptr ] = FREE_KEY;
+ else
+ m_data[ ptr ] = REMOVED_KEY;
+ final V ret = (V) m_data[ ptr + 1 ];
+ m_data[ ptr + 1 ] = null;
+ return ret;
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private V insertNullKey(final V value)
+ {
+ if ( m_hasNull )
+ {
+ final Object ret = m_nullValue;
+ m_nullValue = value;
+ return (V) ret;
+ }
+ else
+ {
+ m_nullValue = value;
+ ++m_size;
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private V removeNullKey()
+ {
+ if ( m_hasNull )
+ {
+ final Object ret = m_nullValue;
+ m_nullValue = null;
+ m_hasNull = false;
+ --m_size;
+ return (V) ret;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public int size()
+ {
+ return m_size;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void rehash( final int newCapacity )
+ {
+ m_threshold = (int) (newCapacity/2 * m_fillFactor);
+ m_mask = newCapacity/2 - 1;
+ m_mask2 = newCapacity - 1;
+
+ final int oldCapacity = m_data.length;
+ final Object[] oldData = m_data;
+
+ m_data = new Object[ newCapacity ];
+ Arrays.fill( m_data, FREE_KEY );
+
+ m_size = m_hasNull ? 1 : 0;
+
+ for ( int i = 0; i < oldCapacity; i += 2 ) {
+ final Object oldKey = oldData[ i ];
+ if( oldKey != FREE_KEY && oldKey != REMOVED_KEY )
+ put( (K)oldKey, (V)oldData[ i + 1 ]);
+ }
+ }
+
+ public int getStartIndex( final Object key )
+ {
+ //key is not null here
+ return key.hashCode() & m_mask;
+ }
+
+ public Object[] values() {
+ return m_data;
+ }
+
+ /** Taken from FastUtil implementation */
+
+ /** Return the least power of two greater than or equal to the specified value.
+ *
+ * <p>Note that this function will return 1 when the argument is 0.
+ *
+ * @param x a long integer smaller than or equal to 2<sup>62</sup>.
+ * @return the least power of two greater than or equal to the specified value.
+ */
+ public static long nextPowerOfTwo( long x ) {
+ if ( x == 0 ) return 1;
+ x--;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return ( x | x >> 32 ) + 1;
+ }
+
+ /** Returns the least power of two smaller than or equal to 2<sup>30</sup> and larger than or equal to <code>Math.ceil( expected / f )</code>.
+ *
+ * @param expected the expected number of elements in a hash table.
+ * @param f the load factor.
+ * @return the minimum possible size for a backing array.
+ * @throws IllegalArgumentException if the necessary size is larger than 2<sup>30</sup>.
+ */
+ public static int arraySize( final int expected, final float f ) {
+ final long s = Math.max( 2, nextPowerOfTwo( (long)Math.ceil( expected / f ) ) );
+ if ( s > (1 << 30) ) throw new IllegalArgumentException( "Too large (" + expected + " expected elements with load factor " + f + ")" );
+ return (int)s;
+ }
+
+ //taken from FastUtil
+ private static final int INT_PHI = 0x9E3779B9;
+
+ public static int phiMix( final int x ) {
+ final int h = x * INT_PHI;
+ return h ^ (h >> 16);
+}
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/data/Pair.java b/src/main/java/gtPlusPlus/api/objects/data/Pair.java
new file mode 100644
index 0000000000..e1d23e6b43
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/Pair.java
@@ -0,0 +1,35 @@
+package gtPlusPlus.api.objects.data;
+
+import java.io.Serializable;
+
+import com.google.common.base.Objects;
+
+public class Pair<K,V> implements Serializable {
+
+ /**
+ * SVUID
+ */
+ private static final long serialVersionUID = 1250550491092812443L;
+ private final K key;
+ private final V value;
+
+ public Pair(final K key, final V value){
+ this.key = key;
+ this.value = value;
+ }
+
+ final public K getKey(){
+ return this.key;
+ }
+
+ final public V getValue(){
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ Integer aCode = Objects.hashCode(getKey(), getValue());
+ return aCode != null ? aCode : super.hashCode();
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/objects/data/Quad.java b/src/main/java/gtPlusPlus/api/objects/data/Quad.java
new file mode 100644
index 0000000000..fa2e52951e
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/Quad.java
@@ -0,0 +1,45 @@
+package gtPlusPlus.api.objects.data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Quad<K,V,C,R> {
+
+ private final K key;
+ private final V value;
+ private final C value2;
+ private final R value3;
+
+ public Quad(final K key, final V value, final C value2, final R value3){
+ this.key = key;
+ this.value = value;
+ this.value2 = value2;
+ this.value3 = value3;
+ }
+
+ final public K getKey(){
+ return this.key;
+ }
+
+ final public V getValue_1(){
+ return this.value;
+ }
+
+ final public C getValue_2(){
+ return this.value2;
+ }
+
+ final public R getValue_3(){
+ return this.value3;
+ }
+
+ public final List values() {
+ List<Object> aVals = new ArrayList<Object>();
+ aVals.add(key);
+ aVals.add(value);
+ aVals.add(value2);
+ aVals.add(value3);
+ return aVals;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/objects/data/ReverseAutoMap.java b/src/main/java/gtPlusPlus/api/objects/data/ReverseAutoMap.java
new file mode 100644
index 0000000000..72ec0bc293
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/ReverseAutoMap.java
@@ -0,0 +1,175 @@
+package gtPlusPlus.api.objects.data;
+
+import java.util.*;
+
+public class ReverseAutoMap<N> extends AutoMap<N> {
+
+ /**
+ * The Internal Map
+ */
+ private Map<N, Integer> mInternalMapReverseLookup = new HashMap<N, Integer>();
+
+ /**
+ * The Internal ID
+ */
+ private int mInternalID = 0;
+ private static final long serialVersionUID = 3771412318075131790L;
+
+ @Override
+ public Iterator<N> iterator() {
+ return values().iterator();
+ }
+
+ public synchronized boolean setValue(N object){
+ int mOriginalID = this.mInternalID;
+ put(object);
+ if (this.mInternalMap.get(mOriginalID).equals(object) || mOriginalID > this.mInternalID){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ @Override
+ public synchronized N put(N object){
+ return set(object);
+ }
+
+ @Override
+ public synchronized N set(N object){
+ int newID = getNextFreeMapID();
+ mInternalMapReverseLookup.put(object, newID);
+ return mInternalMap.put(newID, object);
+ }
+
+ public synchronized int putToInternalMap(N object){
+ return setInternalMap(object);
+ }
+
+ public synchronized int setInternalMap(N object){
+ int newID = getNextFreeMapID();
+ mInternalMap.put(newID, object);
+ mInternalMapReverseLookup.put(object, newID);
+ return newID;
+ }
+
+ public synchronized boolean injectCleanDataToAutoMap(Integer g, N object){
+ if (!mInternalMap.containsKey(g) && !mInternalMapReverseLookup.containsKey(object)) {
+ int a1 = 0, a2 = 0, a11 = 0, a22 = 0;
+ a1 = mInternalMap.size();
+ a2 = mInternalMapReverseLookup.size();
+ a11 = a1;
+ a22 = a2;
+ mInternalMap.put(g, object);
+ a1 = mInternalMap.size();
+ mInternalMapReverseLookup.put(object, g);
+ a2 = mInternalMapReverseLookup.size();
+ if (a1 > a11 && a2 > a22)
+ return true;
+ }
+ return false;
+ }
+
+ public synchronized boolean injectDataToAutoMap(Integer g, N object){
+ int a1 = 0, a2 = 0, a11 = 0, a22 = 0;
+ a1 = mInternalMap.size();
+ a2 = mInternalMapReverseLookup.size();
+ a11 = a1;
+ a22 = a2;
+ mInternalMap.put(g, object);
+ a1 = mInternalMap.size();
+ mInternalMapReverseLookup.put(object, g);
+ a2 = mInternalMapReverseLookup.size();
+ if (a1 > a11 && a2 > a22)
+ return true;
+ return false;
+ }
+
+ private boolean raiseInternalID() {
+ int mOld = mInternalID;
+ mInternalID++;
+ return mInternalID > mOld;
+ }
+
+ public synchronized int getNextFreeMapID() {
+ if (raiseInternalID()) {
+ return mInternalID;
+ }
+ return Short.MIN_VALUE;
+ }
+
+ @Override
+ public synchronized N get(int id){
+ return mInternalMap.get(id);
+ }
+
+ public synchronized int get(N key) {
+ return mInternalMapReverseLookup.get(key);
+ }
+
+ @Override
+ public synchronized Collection<N> values(){
+ return mInternalMap.values();
+ }
+
+ public synchronized Collection<Integer> keys(){
+ return mInternalMapReverseLookup.values();
+ }
+
+ @Override
+ public synchronized int size(){
+ return mInternalMap.size();
+ }
+
+ @Override
+ public synchronized int hashCode(){
+ return mInternalMap.hashCode()+mInternalMapReverseLookup.hashCode();
+ }
+
+ @Override
+ public synchronized boolean containsKey(int key){
+ return mInternalMap.containsKey(key);
+ }
+
+ @Override
+ public synchronized boolean containsValue(N value){
+ return mInternalMap.containsValue(value);
+ }
+
+ public synchronized boolean containsKey(N key){
+ return mInternalMapReverseLookup.containsKey(key);
+ }
+
+ public synchronized boolean containsValue(int value){
+ return mInternalMapReverseLookup.containsValue(value);
+ }
+
+ @Override
+ public synchronized boolean isEmpty(){
+ return mInternalMap.isEmpty() && mInternalMapReverseLookup.isEmpty();
+ }
+
+ @Override
+ public synchronized void clear(){
+ this.mInternalID = 0;
+ this.mInternalMap.clear();
+ this.mInternalMapReverseLookup.clear();
+ return;
+ }
+
+ @Override
+ public synchronized N[] toArray() {
+ Collection<N> col = this.mInternalMap.values();
+ @SuppressWarnings("unchecked")
+ N[] val = (N[]) col.toArray();
+ return val;
+ }
+
+ public synchronized Integer[] toArrayInternalMap() {
+ Collection<Integer> col = this.mInternalMapReverseLookup.values();
+ Integer[] val = col.toArray(new Integer[col.size()]);
+ return val;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/data/Triplet.java b/src/main/java/gtPlusPlus/api/objects/data/Triplet.java
new file mode 100644
index 0000000000..affb03d868
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/Triplet.java
@@ -0,0 +1,27 @@
+package gtPlusPlus.api.objects.data;
+
+public class Triplet<K,V,C> {
+
+ private final K key;
+ private final V value;
+ private final C count;
+
+ public Triplet(final K key, final V value, final C value2){
+ this.key = key;
+ this.value = value;
+ this.count = value2;
+ }
+
+ final public K getValue_1(){
+ return this.key;
+ }
+
+ final public V getValue_2(){
+ return this.value;
+ }
+
+ final public C getValue_3(){
+ return this.count;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/objects/data/TypeCounter.java b/src/main/java/gtPlusPlus/api/objects/data/TypeCounter.java
new file mode 100644
index 0000000000..601a51392f
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/TypeCounter.java
@@ -0,0 +1,178 @@
+package gtPlusPlus.api.objects.data;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import gtPlusPlus.api.objects.Logger;
+
+
+public class TypeCounter<V> implements Set<V> {
+
+ private Map<String, InternalTypeCounterObject<V>> mInternalMap = new LinkedHashMap<String, InternalTypeCounterObject<V>>();
+ private String mHighestValueKey;
+ private int mHighestValue = 0;
+ private final Class mClass;
+
+ public TypeCounter(Class o) {
+ Logger.WARNING("Created new TypeCounter for "+o.getName());
+ mClass = o;
+ }
+
+ public static class InternalTypeCounterObject<Z> {
+ private final Z mObject;
+ private int mCounter = 0;
+
+ public InternalTypeCounterObject(Z o) {
+ mObject = o;
+ }
+
+ public String hash() {
+ return String.valueOf(mObject.hashCode());
+ }
+
+ public Z get() {
+ return mObject;
+ }
+
+ public void add() {
+ mCounter++;
+ }
+
+ public int count() {
+ return mCounter;
+ }
+
+ }
+
+ public boolean add(V arg0) {
+ return add(arg0, null);
+ }
+
+ public boolean add(V arg0, String aKeyName) {
+ String aKey = aKeyName != null ? aKeyName : arg0.toString();
+ InternalTypeCounterObject<V> aValue = mInternalMap.get(aKey);
+ if (aValue == null) {
+ aValue = new InternalTypeCounterObject<V>((V) arg0);
+ Logger.WARNING("Adding new key to map: "+aKey);
+ }
+ aValue.add();
+ int a = aValue.count();
+ if (a > mHighestValue) {
+ mHighestValue = a;
+ mHighestValueKey = aKey;
+ Logger.WARNING("New Highest Count - "+aKey+":"+a);
+ }
+ mInternalMap.put(aKey, aValue);
+ Logger.WARNING(aKey+":"+a);
+ return true;
+ }
+
+ @Override
+ public boolean addAll(Collection arg0) {
+ boolean aReturn = true;
+ for (Object o : arg0) {
+ if (mClass.isInstance(o)) {
+ V j = (V) o;
+ boolean b = add(j);
+ if (!b) {
+ aReturn = false;
+ }
+ }
+ }
+ return aReturn;
+ }
+
+ @Override
+ public void clear() {
+ mInternalMap.clear();
+ }
+
+ @Override
+ public boolean contains(Object arg0) {
+ return mInternalMap.containsKey(arg0.toString());
+ }
+
+ @Override
+ public boolean containsAll(Collection arg0) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mInternalMap.isEmpty();
+ }
+
+ @Override
+ public Iterator iterator() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean remove(Object arg0) {
+ InternalTypeCounterObject<V> aValue = mInternalMap.remove(arg0.toString());
+ if (aValue != null) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean removeAll(Collection arg0) {
+ boolean aReturn = true;
+ for (Object o : arg0) {
+ boolean a = remove(o);
+ if (!a) {
+ aReturn = false;
+ }
+ }
+ return aReturn;
+ }
+
+ @Override
+ public boolean retainAll(Collection arg0) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public int size() {
+ return this.mInternalMap.size();
+ }
+
+ @Override
+ public Object[] toArray() {
+ Object[] aArray = new Object[this.mInternalMap.size()];
+ int aPos = 0;
+ for (String k : this.mInternalMap.keySet()) {
+ if (k != null) {
+ InternalTypeCounterObject<V> aVal = this.mInternalMap.get(k);
+ aArray[aPos++] = new Pair<String, InternalTypeCounterObject<V>>(k, aVal);
+ }
+ }
+ return aArray;
+ }
+
+ @Override
+ public V[] toArray(Object[] a) {
+ Object[] aArray = new Object[a.length];
+ int aPos = 0;
+ for (Object k : a) {
+ if (k != null) {
+ aArray[aPos++] = k;
+ }
+ }
+ return (V[]) aArray;
+ }
+
+ public V getResults() {
+ InternalTypeCounterObject<V> x = mInternalMap.get(mHighestValueKey);
+ return x.get();
+ }
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/data/WeightedCollection.java b/src/main/java/gtPlusPlus/api/objects/data/WeightedCollection.java
new file mode 100644
index 0000000000..f9966474b0
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/WeightedCollection.java
@@ -0,0 +1,102 @@
+package gtPlusPlus.api.objects.data;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.Random;
+import java.util.Set;
+import java.util.TreeMap;
+
+import gtPlusPlus.api.objects.random.XSTR;
+
+public class WeightedCollection<E> implements Map<Integer, E> {
+
+ private NavigableMap<Integer, E> map = new TreeMap<Integer, E>();
+ private Random random;
+ private int total = 0;
+
+ public WeightedCollection() {
+ this(new XSTR());
+ }
+
+ public WeightedCollection(Random random) {
+ this.random = random;
+ }
+
+ public E add(int weight, E object) {
+ if (weight <= 0) return null;
+ total += weight;
+ return map.put(total, object);
+ }
+
+ private E next() {
+ int value = random.nextInt(total) + 1; // Can also use floating-point weights
+ return map.ceilingEntry(value).getValue();
+ }
+
+ @Override
+ public int size() {
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return map.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return map.containsValue(value);
+ }
+
+ public E get() {
+ return next();
+ }
+
+ @Override
+ public E get(Object key) {
+ return next();
+ }
+
+ @Override
+ public void putAll(Map m) {
+ map.putAll(m);
+ }
+
+ @Override
+ public void clear() {
+ map.clear();
+ this.total = 0;
+ }
+
+ @Override
+ public Set keySet() {
+ return map.keySet();
+ }
+
+ @Override
+ public Collection values() {
+ return map.values();
+ }
+
+ @Override
+ public Set entrySet() {
+ return map.entrySet();
+ }
+
+ @Override
+ public E put(Integer key, E value) {
+ return add(key, value);
+ }
+
+ @Override
+ public E remove(Object key) {
+ return map.remove(key);
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/objects/data/weakref/WeakAutoMap.java b/src/main/java/gtPlusPlus/api/objects/data/weakref/WeakAutoMap.java
new file mode 100644
index 0000000000..6c55822ca9
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/data/weakref/WeakAutoMap.java
@@ -0,0 +1,12 @@
+package gtPlusPlus.api.objects.data.weakref;
+
+import java.util.WeakHashMap;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+
+public class WeakAutoMap<T> extends AutoMap<T> {
+ private static final long serialVersionUID = 8328345351801363386L;
+ public WeakAutoMap() {
+ super(new WeakHashMap<Integer, T>());
+ }
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/AABB.java b/src/main/java/gtPlusPlus/api/objects/minecraft/AABB.java
new file mode 100644
index 0000000000..722ac00b64
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/AABB.java
@@ -0,0 +1,65 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import gtPlusPlus.core.util.minecraft.EntityUtils;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.world.World;
+
+/**
+ * Generates an AABB around an entity.
+ * @author Alkalus
+ *
+ */
+public class AABB {
+
+ private final AxisAlignedBB mAabb;
+ private final World mWorld;
+
+ /**
+ * Creates a AxisAlignedBB based around an Entity.
+ * @param aEntity - The Entity to work with.
+ * @param x - Maximum X from origin.
+ * @param y - Maximum Y from origin.
+ * @param z - Maximum Z from origin.
+ */
+ public AABB(Entity aEntity, int x, int y, int z) {
+ if (aEntity == null) {
+ mAabb = null;
+ mWorld = null;
+ }
+ else {
+ mWorld = aEntity.worldObj;
+ BlockPos aEntityLocation = EntityUtils.findBlockPosUnderEntity(aEntity);
+ int xMin, xMax, yMin, yMax, zMin, zMax;
+ xMin = aEntityLocation.xPos;
+ yMin = aEntityLocation.yPos;
+ zMin = aEntityLocation.zPos;
+ xMax = aEntityLocation.xPos + x;
+ yMax = aEntityLocation.yPos + y;
+ zMax = aEntityLocation.zPos + z;
+ mAabb = AxisAlignedBB.getBoundingBox(xMin, yMin, zMin, xMax, yMax, zMax);
+ }
+
+ }
+
+ /**
+ * Used to get the AxisAlignedBB from this class.
+ * @return
+ */
+ public AxisAlignedBB get() {
+ return mAabb;
+ }
+
+ /**
+ * Used to determine if this object is valid or not.
+ * @return
+ */
+ public boolean valid() {
+ return mAabb != null && mWorld != null;
+ }
+
+ public World world() {
+ return mWorld;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_FluidTank.java b/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_FluidTank.java
new file mode 100644
index 0000000000..0b8f97b378
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_FluidTank.java
@@ -0,0 +1,188 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import gtPlusPlus.core.util.minecraft.FluidUtils;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTank;
+import net.minecraftforge.fluids.FluidTankInfo;
+
+public class BTF_FluidTank extends FluidTank {
+
+ public FluidStack mFluid;
+
+ public BTF_FluidTank(int capacity) {
+ super(capacity);
+ }
+
+ /**
+ * Let's replace the Default handling with GT's own handling code, because it's probably better, right?
+ * @author Alkalus/GregoriusT
+ */
+
+
+ public FluidStack getFluid() {
+ return this.getDrainableStack();
+ }
+
+ public int getFluidAmount() {
+ return this.getDrainableStack() != null ? this.getDrainableStack().amount : 0;
+ }
+
+ public NBTTagCompound writeToNBT(NBTTagCompound aNBT) {
+ super.writeToNBT(aNBT);
+ if (this.mFluid != null) {
+ aNBT.setTag("mFluid", this.mFluid.writeToNBT(new NBTTagCompound()));
+ }
+ return aNBT;
+ }
+
+ public FluidTank readFromNBT(NBTTagCompound aNBT) {
+ this.mFluid = FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag("mFluid"));
+ return this;
+ }
+
+/* public abstract boolean isLiquidInput(byte arg0);
+
+ public abstract boolean isLiquidOutput(byte arg0);
+
+ public abstract boolean doesFillContainers();
+
+ public abstract boolean doesEmptyContainers();*/
+
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ public boolean canTankBeEmptied() {
+ return true;
+ }
+
+
+ public boolean isFluidInputAllowed(FluidStack aFluid) {
+ return true;
+ }
+
+ public FluidStack getFillableStack() {
+ return this.mFluid;
+ }
+
+ public FluidStack setFillableStack(FluidStack aFluid) {
+ this.mFluid = aFluid;
+ return this.mFluid;
+ }
+
+ public FluidStack getDrainableStack() {
+ return this.mFluid;
+ }
+
+ public FluidStack setDrainableStack(FluidStack aFluid) {
+ this.mFluid = aFluid;
+ return this.mFluid;
+ }
+
+ public FluidStack getDisplayedFluid() {
+ return this.getDrainableStack();
+ }
+
+ public boolean isFluidChangingAllowed() {
+ return true;
+ }
+
+ public int fill(FluidStack aFluid, boolean doFill) {
+ if (aFluid != null && aFluid.getFluid().getID() > 0 && aFluid.amount > 0 && this.canTankBeFilled()
+ && this.isFluidInputAllowed(aFluid)) {
+ if (this.getFillableStack() != null && this.getFillableStack().getFluid().getID() > 0) {
+ if (!this.getFillableStack().isFluidEqual(aFluid)) {
+ return 0;
+ } else {
+ int space = this.getCapacity() - this.getFillableStack().amount;
+ if (aFluid.amount <= space) {
+ if (doFill) {
+ FluidStack arg9999 = this.getFillableStack();
+ arg9999.amount += aFluid.amount;
+ }
+
+ return aFluid.amount;
+ } else {
+ if (doFill) {
+ this.getFillableStack().amount = this.getCapacity();
+ }
+
+ return space;
+ }
+ }
+ } else if (aFluid.amount <= this.getCapacity()) {
+ if (doFill) {
+ this.setFillableStack(aFluid.copy());
+ }
+
+ return aFluid.amount;
+ } else {
+ if (doFill) {
+ this.setFillableStack(aFluid.copy());
+ this.getFillableStack().amount = this.getCapacity();
+ }
+
+ return this.getCapacity();
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ public FluidStack drain(int maxDrain, boolean doDrain) {
+ if (this.getDrainableStack() != null && this.canTankBeEmptied()) {
+ if (this.getDrainableStack().amount <= 0 && this.isFluidChangingAllowed()) {
+ this.setDrainableStack((FluidStack) null);
+ return null;
+ } else {
+ int used = maxDrain;
+ if (this.getDrainableStack().amount < maxDrain) {
+ used = this.getDrainableStack().amount;
+ }
+
+ if (doDrain) {
+ FluidStack arg9999 = this.getDrainableStack();
+ arg9999.amount -= used;
+ }
+
+ FluidStack drained = this.getDrainableStack().copy();
+ drained.amount = used;
+ if (this.getDrainableStack().amount <= 0 && this.isFluidChangingAllowed()) {
+ this.setDrainableStack((FluidStack) null);
+ }
+
+ return drained;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public int getCapacity() {
+ return super.getCapacity();
+ }
+
+ @Override
+ public FluidTankInfo getInfo() {
+ return new FluidTankInfo(this);
+ }
+
+ @Override
+ public void setFluid(FluidStack fluid) {
+ setFillableStack(fluid);
+ }
+
+ @Override
+ public void setCapacity(int capacity) {
+ super.setCapacity(capacity);
+ }
+
+ public FluidStack drain(FluidStack aFluid, boolean doDrain) {
+ return drain(aFluid.amount, doDrain);
+ }
+
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_Inventory.java b/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_Inventory.java
new file mode 100644
index 0000000000..04ce0dff19
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_Inventory.java
@@ -0,0 +1,228 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import java.util.ArrayList;
+
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.tileentities.base.TileEntityBase;
+import gtPlusPlus.core.util.data.ArrayUtils;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.ISidedInventory;
+import net.minecraft.item.ItemStack;
+
+public class BTF_Inventory implements ISidedInventory{
+
+ public final ItemStack[] mInventory;
+ public final TileEntityBase mTile;
+
+ public BTF_Inventory(int aSlots, TileEntityBase tile) {
+ this.mInventory = new ItemStack[aSlots];
+ this.mTile = tile;
+ }
+
+ public ItemStack[] getRealInventory() {
+ purgeNulls();
+ return this.mInventory;
+ }
+
+ public int getSizeInventory() {
+ return this.mInventory.length;
+ }
+
+ public ItemStack getStackInSlot(int aIndex) {
+ return aIndex >= 0 && aIndex < this.mInventory.length ? this.mInventory[aIndex] : null;
+ }
+
+ public void setInventorySlotContents(int aIndex, ItemStack aStack) {
+ if (aIndex >= 0 && aIndex < this.mInventory.length) {
+ this.mInventory[aIndex] = aStack;
+ }
+ }
+
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+
+ public boolean setStackToZeroInsteadOfNull(int aIndex) {
+ return false;
+}
+
+ public boolean isItemValidForSlot(int aIndex, ItemStack aStack) {
+ return isValidSlot(aIndex);
+ }
+
+ public ItemStack decrStackSize(int aIndex, int aAmount) {
+ ItemStack tStack = this.getStackInSlot(aIndex);
+ ItemStack rStack = GT_Utility.copy(new Object[]{tStack});
+ if (tStack != null) {
+ if (tStack.stackSize <= aAmount) {
+ if (this.setStackToZeroInsteadOfNull(aIndex)) {
+ tStack.stackSize = 0;
+ } else {
+ this.setInventorySlotContents(aIndex, (ItemStack) null);
+ }
+ } else {
+ rStack = tStack.splitStack(aAmount);
+ if (tStack.stackSize == 0 && !this.setStackToZeroInsteadOfNull(aIndex)) {
+ this.setInventorySlotContents(aIndex, (ItemStack) null);
+ }
+ }
+ }
+
+ return rStack;
+ }
+
+ public int[] getAccessibleSlotsFromSide(int aSide) {
+ ArrayList<Integer> tList = new ArrayList<Integer>();
+ TileEntityBase tTileEntity = this.mTile;
+ boolean tSkip = tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide,
+ tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2,
+ tTileEntity)
+ || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide,
+ tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2,
+ tTileEntity);
+
+ for (int rArray = 0; rArray < this.getSizeInventory(); ++rArray) {
+ if (this.isValidSlot(rArray) && (tSkip
+ || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide,
+ tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide),
+ rArray, tTileEntity)
+ || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide,
+ tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide),
+ rArray, tTileEntity))) {
+ tList.add(Integer.valueOf(rArray));
+ }
+ }
+
+ int[] arg6 = new int[tList.size()];
+
+ for (int i = 0; i < arg6.length; ++i) {
+ arg6[i] = ((Integer) tList.get(i)).intValue();
+ }
+
+ return arg6;
+ }
+
+ public boolean canInsertItem(int aIndex, ItemStack aStack, int aSide) {
+ return this.isValidSlot(aIndex) && aStack != null && aIndex < this.mInventory.length
+ && (this.mInventory[aIndex] == null || GT_Utility.areStacksEqual(aStack, this.mInventory[aIndex]))
+ && this.allowPutStack(this.mTile, aIndex, (byte) aSide, aStack);
+ }
+
+ public boolean canExtractItem(int aIndex, ItemStack aStack, int aSide) {
+ return this.isValidSlot(aIndex) && aStack != null && aIndex < this.mInventory.length
+ && this.allowPullStack(this.mTile, aIndex, (byte) aSide, aStack);
+ }
+
+ public boolean allowPullStack(TileEntityBase mTile2, int aIndex, byte aSide, ItemStack aStack) {
+ return aIndex >= 0 && aIndex < this.getSizeInventory();
+ }
+
+ public boolean allowPutStack(TileEntityBase aBaseMetaTileEntity, int aIndex, byte aSide, ItemStack aStack) {
+ return (aIndex >= 0 && aIndex < this.getSizeInventory()) && (this.mInventory[aIndex] == null || GT_Utility.areStacksEqual(this.mInventory[aIndex], aStack));
+ }
+
+ public ItemStack getStackInSlotOnClosing(int i) {
+ return null;
+ }
+
+ public final boolean hasCustomInventoryName() {
+ return mTile != null ? mTile.hasCustomInventoryName() : false;
+ }
+
+
+ public void markDirty() {
+ if (mTile != null) {
+ purgeNulls();
+ mTile.markDirty();
+ }
+ }
+
+ public boolean isUseableByPlayer(EntityPlayer entityplayer) {
+ return true;
+ }
+
+ public void openInventory() {
+
+ }
+
+ public void closeInventory() {
+
+ }
+
+ @Override
+ public final String getInventoryName() {
+ return this.mTile != null ? mTile.getInventoryName() : "";
+ }
+
+ public boolean isFull() {
+ for (int s=0;s<this.getSizeInventory();s++) {
+ ItemStack slot = mInventory[s];
+ if (slot == null || slot.stackSize != slot.getMaxStackSize()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean isEmpty() {
+ for (int s=0;s<this.getSizeInventory();s++) {
+ ItemStack slot = mInventory[s];
+ if (slot == null) {
+ continue;
+ }
+ else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean addItemStack(ItemStack aInput) {
+ if (aInput != null & (isEmpty() || !isFull())) {
+ for (int s = 0; s < this.getSizeInventory(); s++) {
+ if (mInventory != null && mInventory[s] != null) {
+ ItemStack slot = mInventory[s];
+ if (slot == null || (slot != null && GT_Utility.areStacksEqual(aInput, slot) && slot.stackSize != slot.getItem().getItemStackLimit(slot))) {
+ if (slot == null) {
+ slot = aInput.copy();
+ } else {
+ slot.stackSize++;
+ }
+ this.setInventorySlotContents(s, slot);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public final void purgeNulls() {
+ ItemStack[] aTemp = ArrayUtils.removeNulls(this.mInventory);
+ for (int g=0;g<this.getSizeInventory();g++) {
+ if (aTemp.length < this.getSizeInventory()) {
+ if (g <= aTemp.length-1) {
+ this.mInventory[g] = aTemp[g];
+ }
+ else {
+ this.mInventory[g] = null;
+ }
+ }
+ else {
+ this.mInventory[g] = aTemp[g];
+ }
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/BlockPos.java b/src/main/java/gtPlusPlus/api/objects/minecraft/BlockPos.java
new file mode 100644
index 0000000000..ab359c3853
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/BlockPos.java
@@ -0,0 +1,250 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import net.minecraft.block.Block;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+import net.minecraftforge.common.DimensionManager;
+
+public class BlockPos implements Serializable{
+
+ private static final long serialVersionUID = -7271947491316682006L;
+ public final int xPos;
+ public final int yPos;
+ public final int zPos;
+ public final int dim;
+ public final transient World world;
+
+ public static BlockPos generateBlockPos(String sUUID) {
+ String[] s2 = sUUID.split("@");
+ return new BlockPos(s2);
+ }
+
+ public BlockPos(String[] s){
+ this(Integer.parseInt(s[1]), Integer.parseInt(s[2]), Integer.parseInt(s[3]), Integer.parseInt(s[0]));
+ }
+
+ public BlockPos(int x, int y, int z){
+ this(x, y, z, 0);
+ }
+
+ public BlockPos(int x, int y, int z, int dim){
+ this(x, y, z, DimensionManager.getWorld(dim));
+ }
+
+ public BlockPos(int x, int y, int z, World dim){
+ this.xPos = x;
+ this.yPos = y;
+ this.zPos = z;
+
+ if (dim != null) {
+ this.dim = dim.provider.dimensionId;
+ this.world = dim;
+ }
+ else {
+ this.dim = 0;
+ this.world = null;
+ }
+
+ }
+
+ public BlockPos(IGregTechTileEntity b) {
+ this (b.getXCoord(), b.getYCoord(), b.getZCoord(), b.getWorld());
+ }
+
+ public BlockPos(TileEntity b) {
+ this (b.xCoord, b.yCoord, b.zCoord, b.getWorldObj());
+ }
+
+ public String getLocationString() {
+ return "[X: "+this.xPos+"][Y: "+this.yPos+"][Z: "+this.zPos+"][Dim: "+this.dim+"]";
+ }
+
+ public String getUniqueIdentifier() {
+ String S = ""+this.dim+"@"+this.xPos+"@"+this.yPos+"@"+this.zPos;
+ return S;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash += (13 * this.xPos);
+ hash += (19 * this.yPos);
+ hash += (31 * this.zPos);
+ hash += (17 * this.dim);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) {
+ return false;
+ }
+ if (other == this) {
+ return true;
+ }
+ if(!(other instanceof BlockPos)) {
+ return false;
+ }
+ BlockPos otherPoint = (BlockPos)other;
+ return this.xPos == otherPoint.xPos && this.yPos == otherPoint.yPos && this.zPos == otherPoint.zPos && this.dim == otherPoint.dim;
+ }
+
+ public int distanceFrom(BlockPos target) {
+ if (target.dim != this.dim) {
+ return Short.MIN_VALUE;
+ }
+ return distanceFrom(target.xPos, target.yPos, target.zPos);
+ }
+
+ /**
+ *
+ * @param x X coordinate of target.
+ * @param y Y coordinate of target.
+ * @param z Z coordinate of target.
+ * @return square of distance
+ */
+ public int distanceFrom(int x, int y, int z) {
+ int distanceX = this.xPos - x;
+ int distanceY = this.yPos - y;
+ int distanceZ = this.zPos - z;
+ return distanceX * distanceX + distanceY * distanceY + distanceZ * distanceZ;
+ }
+
+ public boolean isWithinRange(BlockPos target, int range) {
+ if (target.dim != this.dim) {
+ return false;
+ }
+ return isWithinRange(target.xPos, target.yPos, target.zPos, range);
+ }
+
+ public boolean isWithinRange(int x, int y, int z, int range) {
+ return distanceFrom(x, y, z) <= (range * range);
+ }
+
+
+ public BlockPos getUp() {
+ return new BlockPos(this.xPos, this.yPos+1, this.zPos, this.dim);
+ }
+
+ public BlockPos getDown() {
+ return new BlockPos(this.xPos, this.yPos-1, this.zPos, this.dim);
+ }
+
+ public BlockPos getXPos() {
+ return new BlockPos(this.xPos+1, this.yPos, this.zPos, this.dim);
+ }
+
+ public BlockPos getXNeg() {
+ return new BlockPos(this.xPos-1, this.yPos, this.zPos, this.dim);
+ }
+
+ public BlockPos getZPos() {
+ return new BlockPos(this.xPos, this.yPos, this.zPos+1, this.dim);
+ }
+
+ public BlockPos getZNeg() {
+ return new BlockPos(this.xPos, this.yPos, this.zPos-1, this.dim);
+ }
+
+ public AutoMap<BlockPos> getSurroundingBlocks(){
+ AutoMap<BlockPos> sides = new AutoMap<BlockPos>();
+ sides.put(getUp());
+ sides.put(getDown());
+ sides.put(getXPos());
+ sides.put(getXNeg());
+ sides.put(getZPos());
+ sides.put(getZNeg());
+ return sides;
+ }
+
+ public Block getBlockAtPos() {
+ return getBlockAtPos(this);
+ }
+
+ public Block getBlockAtPos(BlockPos pos) {
+ return getBlockAtPos(world, pos);
+ }
+
+ public Block getBlockAtPos(World world, BlockPos pos) {
+ return world.getBlock(pos.xPos, pos.yPos, pos.zPos);
+ }
+
+ public int getMetaAtPos() {
+ return getMetaAtPos(this);
+ }
+
+ public int getMetaAtPos(BlockPos pos) {
+ return getMetaAtPos(world, pos);
+ }
+
+ public int getMetaAtPos(World world, BlockPos pos) {
+ return world.getBlockMetadata(pos.xPos, pos.yPos, pos.zPos);
+ }
+
+ public boolean hasSimilarNeighbour() {
+ return hasSimilarNeighbour(false);
+ }
+
+ /**
+ * @param strict - Does this check Meta Data?
+ * @return - Does this block have a neighbour that is the same?
+ */
+ public boolean hasSimilarNeighbour(boolean strict) {
+ for (BlockPos g : getSurroundingBlocks().values()) {
+ if (getBlockAtPos(g) == getBlockAtPos()) {
+ if (!strict) {
+ return true;
+ }
+ else {
+ if (getMetaAtPos() == getMetaAtPos(g)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public AutoMap<BlockPos> getSimilarNeighbour() {
+ return getSimilarNeighbour(false);
+ }
+
+ /**
+ * @param strict - Does this check Meta Data?
+ * @return - Does this block have a neighbour that is the same?
+ */
+ public AutoMap<BlockPos> getSimilarNeighbour(boolean strict) {
+ AutoMap<BlockPos> sides = new AutoMap<BlockPos>();
+ for (BlockPos g : getSurroundingBlocks().values()) {
+ if (getBlockAtPos(g) == getBlockAtPos()) {
+ if (!strict) {
+ sides.put(g);
+ }
+ else {
+ if (getMetaAtPos() == getMetaAtPos(g)) {
+ sides.put(g);
+ }
+ }
+ }
+ }
+ return sides;
+ }
+
+ public Set<BlockPos> getValidNeighboursAndSelf(){
+ AutoMap<BlockPos> h = getSimilarNeighbour(true);
+ h.put(this);
+ Set<BlockPos> result = new HashSet<BlockPos>();
+ for (BlockPos f : h.values()) {
+ result.add(f);
+ }
+ return result;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/CubicObject.java b/src/main/java/gtPlusPlus/api/objects/minecraft/CubicObject.java
new file mode 100644
index 0000000000..8c76513d09
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/CubicObject.java
@@ -0,0 +1,62 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+import net.minecraftforge.common.util.ForgeDirection;
+
+public class CubicObject<T> {
+
+ public final T NORTH;
+ public final T SOUTH;
+
+ public final T WEST;
+ public final T EAST;
+
+ public final T UP;
+ public final T DOWN;
+
+ public CubicObject(AutoMap<T> aDataSet) {
+ this(aDataSet.get(0), aDataSet.get(1), aDataSet.get(2), aDataSet.get(3), aDataSet.get(4), aDataSet.get(5));
+ }
+
+ public CubicObject(T[] aDataSet) {
+ this(aDataSet[0], aDataSet[1], aDataSet[2], aDataSet[3], aDataSet[4], aDataSet[5]);
+ }
+
+ public CubicObject(T aDOWN, T aUP, T aNORTH, T aSOUTH, T aWEST, T aEAST) {
+ DOWN = aDOWN;
+ UP = aUP;
+ NORTH = aNORTH;
+ SOUTH = aSOUTH;
+ WEST = aWEST;
+ EAST = aEAST;
+ }
+
+ public T get(int aSide) {
+ return get(ForgeDirection.getOrientation(aSide));
+ }
+
+ public T get(ForgeDirection aSide) {
+ if (aSide == ForgeDirection.DOWN) {
+ return DOWN;
+ }
+ else if (aSide == ForgeDirection.UP) {
+ return UP;
+ }
+ else if (aSide == ForgeDirection.NORTH) {
+ return NORTH;
+ }
+ else if (aSide == ForgeDirection.SOUTH) {
+ return SOUTH;
+ }
+ else if (aSide == ForgeDirection.WEST) {
+ return WEST;
+ }
+ else if (aSide == ForgeDirection.EAST) {
+ return EAST;
+ }
+ else {
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/DimChunkPos.java b/src/main/java/gtPlusPlus/api/objects/minecraft/DimChunkPos.java
new file mode 100644
index 0000000000..010e522a14
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/DimChunkPos.java
@@ -0,0 +1,52 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+
+public class DimChunkPos {
+
+ public final int dimension;
+ public final int xPos;
+ public final int zPos;
+ public final Chunk mainChunk;
+
+
+ public DimChunkPos(World world, BlockPos block){
+ this.dimension = world.provider.dimensionId;
+ this.mainChunk = world.getChunkFromBlockCoords(block.xPos, block.zPos);
+ this.xPos = this.mainChunk.xPosition;
+ this.zPos = this.mainChunk.zPosition;
+ }
+
+
+ public DimChunkPos(TileEntity tile){
+ this.dimension = tile.getWorldObj().provider.dimensionId;
+ this.mainChunk = tile.getWorldObj().getChunkFromBlockCoords(tile.xCoord, tile.zCoord);
+ this.xPos = this.mainChunk.xPosition;
+ this.zPos = this.mainChunk.zPosition;
+ }
+
+ public DimChunkPos(int dim, int x, int z){
+ this.dimension = dim;
+ this.xPos = x;
+ this.zPos = z;
+ Chunk h = Minecraft.getMinecraft().getIntegratedServer().worldServerForDimension(dim).getChunkFromChunkCoords(xPos, zPos);
+ if (h == null) {
+ this.mainChunk = null;
+ }
+ else {
+ this.mainChunk = h;
+ }
+ }
+
+ public Chunk getChunk() {
+ if (this.mainChunk != null) {
+ return this.mainChunk;
+ }
+ Chunk h = Minecraft.getMinecraft().getIntegratedServer().worldServerForDimension(this.dimension).getChunkFromChunkCoords(xPos, zPos);
+ return h;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/FakeBlockPos.java b/src/main/java/gtPlusPlus/api/objects/minecraft/FakeBlockPos.java
new file mode 100644
index 0000000000..d5db8081dc
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/FakeBlockPos.java
@@ -0,0 +1,253 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.world.World;
+import net.minecraftforge.common.DimensionManager;
+
+public class FakeBlockPos extends BlockPos {
+
+ private static final long serialVersionUID = -6442245826092414593L;
+ private transient Block aBlockAtPos;
+ private int aBlockMetaAtPos = 0;
+
+ public static FakeBlockPos generateBlockPos(String sUUID) {
+ String[] s2 = sUUID.split("@");
+ return new FakeBlockPos(s2);
+ }
+
+ public FakeBlockPos(String[] s){
+ this(Integer.parseInt(s[1]), Integer.parseInt(s[2]), Integer.parseInt(s[3]), Integer.parseInt(s[0]));
+ }
+
+ public FakeBlockPos(int x, int y, int z, Block aBlock, int aMeta){
+ this(x, y, z, 0);
+ aBlockAtPos = aBlock;
+ aBlockMetaAtPos = aMeta;
+ }
+
+ private FakeBlockPos(int x, int y, int z, int dim){
+ this(x, y, z, DimensionManager.getWorld(dim));
+ }
+
+ private FakeBlockPos(int x, int y, int z, World dim){
+ super(x, y, z, null);
+ }
+
+ public String getLocationString() {
+ String S = ""+this.xPos+"@"+this.yPos+"@"+this.zPos;
+ return S;
+ }
+
+ public String getUniqueIdentifier() {
+ String S = ""+this.xPos+"@"+this.yPos+"@"+this.zPos+this.aBlockAtPos.getLocalizedName()+"@"+this.aBlockMetaAtPos;
+ return S;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash += (13 * this.xPos);
+ hash += (19 * this.yPos);
+ hash += (31 * this.zPos);
+ hash += (17 * this.dim);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) {
+ return false;
+ }
+ if (other == this) {
+ return true;
+ }
+ if(!(other instanceof FakeBlockPos)) {
+ return false;
+ }
+ FakeBlockPos otherPoint = (FakeBlockPos) other;
+ return this.xPos == otherPoint.xPos && this.yPos == otherPoint.yPos && this.zPos == otherPoint.zPos;
+ }
+
+ public int distanceFrom(FakeBlockPos target) {
+ if (target.dim != this.dim) {
+ return Short.MIN_VALUE;
+ }
+ return distanceFrom(target.xPos, target.yPos, target.zPos);
+ }
+
+ /**
+ *
+ * @param x X coordinate of target.
+ * @param y Y coordinate of target.
+ * @param z Z coordinate of target.
+ * @return square of distance
+ */
+ public int distanceFrom(int x, int y, int z) {
+ int distanceX = this.xPos - x;
+ int distanceY = this.yPos - y;
+ int distanceZ = this.zPos - z;
+ return distanceX * distanceX + distanceY * distanceY + distanceZ * distanceZ;
+ }
+
+ public boolean isWithinRange(FakeBlockPos target, int range) {
+ if (target.dim != this.dim) {
+ return false;
+ }
+ return isWithinRange(target.xPos, target.yPos, target.zPos, range);
+ }
+
+ public boolean isWithinRange(int x, int y, int z, int range) {
+ return distanceFrom(x, y, z) <= (range * range);
+ }
+
+
+ public FakeBlockPos getUp() {
+ return new FakeBlockPos(this.xPos, this.yPos+1, this.zPos, this.dim);
+ }
+
+ public FakeBlockPos getDown() {
+ return new FakeBlockPos(this.xPos, this.yPos-1, this.zPos, this.dim);
+ }
+
+ public FakeBlockPos getXPos() {
+ return new FakeBlockPos(this.xPos+1, this.yPos, this.zPos, this.dim);
+ }
+
+ public FakeBlockPos getXNeg() {
+ return new FakeBlockPos(this.xPos-1, this.yPos, this.zPos, this.dim);
+ }
+
+ public FakeBlockPos getZPos() {
+ return new FakeBlockPos(this.xPos, this.yPos, this.zPos+1, this.dim);
+ }
+
+ public FakeBlockPos getZNeg() {
+ return new FakeBlockPos(this.xPos, this.yPos, this.zPos-1, this.dim);
+ }
+
+ public AutoMap<BlockPos> getSurroundingBlocks(){
+ AutoMap<BlockPos> sides = new AutoMap<BlockPos>();
+ sides.put(getUp());
+ sides.put(getDown());
+ sides.put(getXPos());
+ sides.put(getXNeg());
+ sides.put(getZPos());
+ sides.put(getZNeg());
+ return sides;
+ }
+
+ public Block getBlockAtPos() {
+ return getBlockAtPos(this);
+ }
+
+ public Block getBlockAtPos(FakeBlockPos pos) {
+ return getBlockAtPos(world, pos);
+ }
+
+ public Block getBlockAtPos(World world, FakeBlockPos pos) {
+ return aBlockAtPos;
+ }
+
+ public int getMetaAtPos() {
+ return getMetaAtPos(this);
+ }
+
+ public int getMetaAtPos(FakeBlockPos pos) {
+ return getMetaAtPos(world, pos);
+ }
+
+ public int getMetaAtPos(World world, FakeBlockPos pos) {
+ return aBlockMetaAtPos;
+ }
+
+ public boolean hasSimilarNeighbour() {
+ return hasSimilarNeighbour(false);
+ }
+
+ /**
+ * @param strict - Does this check Meta Data?
+ * @return - Does this block have a neighbour that is the same?
+ */
+ public boolean hasSimilarNeighbour(boolean strict) {
+ for (BlockPos g : getSurroundingBlocks().values()) {
+ if (getBlockAtPos(g) == getBlockAtPos()) {
+ if (!strict) {
+ return true;
+ }
+ else {
+ if (getMetaAtPos() == getMetaAtPos(g)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public AutoMap<BlockPos> getSimilarNeighbour() {
+ return getSimilarNeighbour(false);
+ }
+
+ /**
+ * @param strict - Does this check Meta Data?
+ * @return - Does this block have a neighbour that is the same?
+ */
+ public AutoMap<BlockPos> getSimilarNeighbour(boolean strict) {
+ AutoMap<BlockPos> sides = new AutoMap<BlockPos>();
+ for (BlockPos g : getSurroundingBlocks().values()) {
+ if (getBlockAtPos(g) == getBlockAtPos()) {
+ if (!strict) {
+ sides.put(g);
+ }
+ else {
+ if (getMetaAtPos() == getMetaAtPos(g)) {
+ sides.put(g);
+ }
+ }
+ }
+ }
+ return sides;
+ }
+
+ public Set<BlockPos> getValidNeighboursAndSelf(){
+ AutoMap<BlockPos> h = getSimilarNeighbour(true);
+ h.put(this);
+ Set<BlockPos> result = new HashSet<BlockPos>();
+ for (BlockPos f : h.values()) {
+ result.add(f);
+ }
+ return result;
+ }
+
+ /**
+ * Called when a plant grows on this block, only implemented for saplings using the WorldGen*Trees classes right now.
+ * Modder may implement this for custom plants.
+ * This does not use ForgeDirection, because large/huge trees can be located in non-representable direction,
+ * so the source location is specified.
+ * Currently this just changes the block to dirt if it was grass.
+ *
+ * Note: This happens DURING the generation, the generation may not be complete when this is called.
+ *
+ * @param world Current world
+ * @param x Soil X
+ * @param y Soil Y
+ * @param z Soil Z
+ * @param sourceX Plant growth location X
+ * @param sourceY Plant growth location Y
+ * @param sourceZ Plant growth location Z
+ */
+ public void onPlantGrow(FakeWorld world, int x, int y, int z, int sourceX, int sourceY, int sourceZ)
+ {
+ if (getBlockAtPos() == Blocks.grass || getBlockAtPos() == Blocks.farmland)
+ {
+ this.aBlockAtPos = Blocks.dirt;
+ this.aBlockMetaAtPos = 0;
+ }
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/FakeWorld.java b/src/main/java/gtPlusPlus/api/objects/minecraft/FakeWorld.java
new file mode 100644
index 0000000000..8ee033a341
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/FakeWorld.java
@@ -0,0 +1,173 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import java.util.HashMap;
+
+import gregtech.api.enums.Materials;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.core.util.math.MathUtils;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.biome.BiomeGenBase;
+import net.minecraftforge.common.util.ForgeDirection;
+
+public class FakeWorld implements IBlockAccess {
+
+ public static HashMap<String, FakeBlockPos> mStaticFakeWorldData;
+
+ public HashMap<String, FakeBlockPos> mFakeWorldData = new HashMap<String, FakeBlockPos>();
+
+ /**
+ * Must be an odd number
+ */
+ private int aWorldSize = 99;
+ private final int aDistanceFromOrigin;
+ private final int aWorldHeight;
+
+ public FakeWorld() {
+ this(99);
+ }
+
+ public FakeWorld(int aSize) {
+ if (MathUtils.isNumberEven(aSize)) {
+ aSize++;
+ }
+ aWorldSize = aSize;
+ aDistanceFromOrigin = ((aWorldSize-1)/2);
+ aWorldHeight = aDistanceFromOrigin >= 255 ? 255 : aDistanceFromOrigin;
+ Logger.WARNING("Created a Fake World with data:");
+ Logger.WARNING("World Size: "+aWorldSize);
+ Logger.WARNING("Distance from Origin in each dir: "+aDistanceFromOrigin);
+ Logger.WARNING("World Height: "+aWorldHeight);
+ init();
+ }
+
+ public void init() {
+
+ /*if (mStaticFakeWorldData == null) {
+ Logger.WARNING("Setting all Blocks in Fake World to Air.");
+ mStaticFakeWorldData = new HashMap<String, FakeBlockPos>();
+ for (int y=0;y<=aWorldHeight;y++) {
+ for (int x=-aDistanceFromOrigin;x<=aDistanceFromOrigin;x++) {
+ for (int z=-aDistanceFromOrigin;z<=aDistanceFromOrigin;z++) {
+ FakeBlockPos aTempPos = new FakeBlockPos(x, y, z, Blocks.air, 0);
+ mStaticFakeWorldData.put(aTempPos.getLocationString(), aTempPos);
+ }
+ }
+ }
+ }*/
+ //if (mStaticFakeWorldData != null) {
+ //Logger.WARNING(" Instancing static air world.");
+ mFakeWorldData = new HashMap<String, FakeBlockPos>();
+ //mFakeWorldData = (HashMap<String, FakeBlockPos>) mStaticFakeWorldData.clone();
+ //}
+
+
+ //Logger.WARNING("Initialisation of FakeWorld is now complete.");
+ }
+
+ public FakeBlockPos getBlockAtCoords(int x, int y, int z) {
+ String S = ""+x+"@"+y+"@"+z;
+ FakeBlockPos aBlock = mFakeWorldData.get(S);
+ if (aBlock == null) {
+ return new FakeBlockPos(x, y, z, Blocks.air, 0);
+ }
+ return aBlock;
+ }
+
+ public void setBlockAtCoords(int x, int y, int z, Block aBlock, int aMeta) {
+ FakeBlockPos aTempPos = new FakeBlockPos(x, y, z, aBlock, aMeta);
+ Logger.WARNING("Setting "+x+", "+y+", "+z+" to "+aBlock.getLocalizedName()+":"+aMeta);
+ mFakeWorldData.put(aTempPos.getLocationString(), aTempPos);
+ }
+
+ public AutoMap<ItemStack> getAllBlocksStoredInFakeWorld(){
+ AutoMap<ItemStack> aOutput = new AutoMap<ItemStack>();
+ for (FakeBlockPos aPos : mFakeWorldData.values()) {
+ if (aPos == null || aPos.getBlockAtPos() == Blocks.air) {
+ continue;
+ }
+ else {
+ ItemStack aTempStack = ItemUtils.simpleMetaStack(aPos.getBlockAtPos(), aPos.getMetaAtPos(), 1);
+ if (ItemUtils.checkForInvalidItems(aTempStack)) {
+ //Logger.WARNING("Output: "+aTempStack.getDisplayName());
+ aOutput.put(aTempStack);
+ }
+ }
+ }
+ return aOutput;
+ }
+
+ public Block getBlock(int x, int y, int z) {
+ FakeBlockPos aPos = getBlockAtCoords(x, y, z);
+ return aPos.getBlockAtPos();
+ }
+
+ public boolean isAirBlock(int x, int y, int z) {
+ Block aBlock = getBlock(x, y, z);
+ return aBlock == Blocks.air || aBlock.getMaterial() == Material.air;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @Override
+ public TileEntity getTileEntity(int p_147438_1_, int p_147438_2_, int p_147438_3_) {
+ return null;
+ }
+
+ @Override
+ public int getLightBrightnessForSkyBlocks(int p_72802_1_, int p_72802_2_, int p_72802_3_, int p_72802_4_) {
+ return 0;
+ }
+
+ @Override
+ public int getBlockMetadata(int x, int y, int z) {
+ return getBlockAtCoords(x, y, z).getMetaAtPos();
+ }
+
+ @Override
+ public int isBlockProvidingPowerTo(int p_72879_1_, int p_72879_2_, int p_72879_3_, int p_72879_4_) {
+ return 0;
+ }
+
+ @Override
+ public BiomeGenBase getBiomeGenForCoords(int p_72807_1_, int p_72807_2_) {
+ return BiomeGenBase.plains;
+ }
+
+ @Override
+ public int getHeight() {
+ return aWorldHeight;
+ }
+
+ @Override
+ public boolean extendedLevelsInChunkCache() {
+ return false;
+ }
+
+ @Override
+ public boolean isSideSolid(int x, int y, int z, ForgeDirection side, boolean _default) {
+ if (!isAirBlock(x, y, z)) {
+ return true;
+ }
+ return false;
+ }
+
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/FluidGT6.java b/src/main/java/gtPlusPlus/api/objects/minecraft/FluidGT6.java
new file mode 100644
index 0000000000..2535046792
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/FluidGT6.java
@@ -0,0 +1,31 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import gregtech.api.GregTech_API;
+
+import gtPlusPlus.core.lib.CORE;
+import net.minecraftforge.fluids.Fluid;
+
+public class FluidGT6 extends Fluid implements Runnable
+{
+ private final short[] mRGBa;
+ public final String mTextureName;
+
+ public FluidGT6(final String aName, final String aTextureName, final short[] aRGBa) {
+ super(aName);
+ this.mRGBa = aRGBa;
+ this.mTextureName = aTextureName;
+ if (GregTech_API.sGTBlockIconload != null) {
+ GregTech_API.sGTBlockIconload.add(this);
+ }
+ }
+
+ @Override
+ public int getColor() {
+ return (Math.max(0, Math.min(255, this.mRGBa[0])) << 16) | (Math.max(0, Math.min(255, this.mRGBa[1])) << 8) | Math.max(0, Math.min(255, this.mRGBa[2]));
+ }
+
+ @Override
+ public void run() {
+ this.setIcons(GregTech_API.sBlockIcons.registerIcon(CORE.MODID+ ":" + "fluids/fluid." + this.mTextureName));
+ }
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/FormattedTooltipString.java b/src/main/java/gtPlusPlus/api/objects/minecraft/FormattedTooltipString.java
new file mode 100644
index 0000000000..ec13c82ea0
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/FormattedTooltipString.java
@@ -0,0 +1,25 @@
+package gtPlusPlus.api.objects.minecraft;
+
+public class FormattedTooltipString {
+
+ public final String mText;
+ public final boolean mPrefix;
+
+ public FormattedTooltipString(String aText, boolean aPrefix) {
+ mText = aText;
+ mPrefix = aPrefix;
+ }
+
+ public String getTooltip(Object aTagValue) {
+ String aTip;
+
+ if (mPrefix) {
+ aTip = mText+": "+aTagValue.toString();
+ }
+ else {
+ aTip = ""+aTagValue.toString()+": "+mText;
+ }
+ return aTip;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/GenericStack.java b/src/main/java/gtPlusPlus/api/objects/minecraft/GenericStack.java
new file mode 100644
index 0000000000..9c1b231961
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/GenericStack.java
@@ -0,0 +1,42 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import net.minecraft.item.ItemStack;
+
+import net.minecraftforge.fluids.FluidStack;
+
+public class GenericStack {
+
+ private ItemStack mItemStack;
+ private FluidStack mFluidStack;
+
+ public GenericStack(ItemStack s){
+ this.mItemStack = s;
+ this.mFluidStack = null;
+ }
+
+ public GenericStack(FluidStack f){
+ this.mItemStack = null;
+ this.mFluidStack = f;
+ }
+
+ public GenericStack() {
+ this.mItemStack = null;
+ this.mFluidStack = null;
+ }
+
+ public synchronized final FluidStack getFluidStack() {
+ return mFluidStack;
+ }
+
+ public synchronized final ItemStack getItemStack() {
+ return mItemStack;
+ }
+
+ public synchronized final void setItemStack(ItemStack mItemStack) {
+ this.mItemStack = mItemStack;
+ }
+
+ public synchronized final void setFluidStack(FluidStack mFluidStack) {
+ this.mFluidStack = mFluidStack;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/ItemPackage.java b/src/main/java/gtPlusPlus/api/objects/minecraft/ItemPackage.java
new file mode 100644
index 0000000000..fa85f23cf3
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/ItemPackage.java
@@ -0,0 +1,58 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
+import gtPlusPlus.api.interfaces.RunnableWithInfo;
+import gtPlusPlus.core.handler.COMPAT_HANDLER;
+
+public abstract class ItemPackage implements RunnableWithInfo<String> {
+
+ public ItemPackage() {
+ this(false);
+ }
+
+ public ItemPackage(boolean hasExtraLateRun) {
+ // Register for late run
+ COMPAT_HANDLER.mObjectsToRunInPostInit.put(this);
+ if (hasExtraLateRun) {
+ COMPAT_HANDLER.mObjectsToRunInOnLoadComplete.put(this);
+ }
+ init();
+ }
+
+ @Override
+ public final void run() {
+ generateRecipes();
+ }
+
+ @Override
+ public final String getInfoData() {
+ return errorMessage();
+ }
+
+ public abstract String errorMessage();
+
+ public abstract boolean generateRecipes();
+
+ private final void init() {
+ items();
+ blocks();
+ fluids();
+ }
+
+ public abstract void items();
+
+ public abstract void blocks();
+
+ public abstract void fluids();
+
+ /**
+ * Override this to handle GT Recipe map manipulation after they're Baked.
+ * @param event - the {@link FMLLoadCompleteEvent}.
+ * @return - Did we do anything?
+ */
+ public boolean onLoadComplete(FMLLoadCompleteEvent event) {
+ return false;
+ };
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/ItemStackData.java b/src/main/java/gtPlusPlus/api/objects/minecraft/ItemStackData.java
new file mode 100644
index 0000000000..476926826b
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/ItemStackData.java
@@ -0,0 +1,35 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+
+public class ItemStackData {
+
+ protected final Item mItem;
+ protected final int mDamage;
+ protected final int mStackSize;
+ protected final NBTTagCompound mNBT;
+ protected final String mUniqueDataTag;
+
+ public ItemStackData (ItemStack aStack) {
+ mItem = aStack.getItem();
+ mDamage = aStack.getItemDamage();
+ mStackSize = aStack.stackSize;
+ mNBT = (aStack.getTagCompound() != null ? aStack.getTagCompound() : new NBTTagCompound());
+ mUniqueDataTag = ""+Item.getIdFromItem(mItem)+""+mDamage+""+mStackSize+""+mNBT.getId();
+ }
+
+ public String getUniqueDataIdentifier() {
+ return this.mUniqueDataTag;
+ }
+
+ public ItemStack getStack() {
+ ItemStack aTemp = ItemUtils.simpleMetaStack(mItem, mDamage, mStackSize);
+ aTemp.setTagCompound(mNBT);
+ return aTemp;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/NoConflictGTRecipeMap.java b/src/main/java/gtPlusPlus/api/objects/minecraft/NoConflictGTRecipeMap.java
new file mode 100644
index 0000000000..78e925fe04
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/NoConflictGTRecipeMap.java
@@ -0,0 +1,123 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Recipe;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+
+public class NoConflictGTRecipeMap implements Collection<GT_Recipe> {
+
+ private AutoMap<GT_Recipe> mRecipeCache = new AutoMap<GT_Recipe>();
+ private final IGregTechTileEntity mMachineType;
+
+ public NoConflictGTRecipeMap () {
+ this(null);
+ }
+
+ public NoConflictGTRecipeMap (IGregTechTileEntity tile0) {
+ this.mMachineType = tile0;
+ }
+ public boolean put(GT_Recipe recipe) {
+ return add(recipe);
+ }
+
+ public boolean add(GT_Recipe recipe) {
+ return mRecipeCache.setValue(recipe);
+ }
+
+ public Collection<GT_Recipe> getRecipeMap() {
+ return mRecipeCache.values();
+ }
+
+ public boolean isMapValidForMachine(IGregTechTileEntity tile) {
+ return tile == mMachineType;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends GT_Recipe> arg0) {
+ int a = 0;
+ for (Object v : arg0) {
+ if (!this.mRecipeCache.containsValue((GT_Recipe) v)) {
+ this.mRecipeCache.put((GT_Recipe) v);
+ a++;
+ }
+ }
+ return a > 0;
+ }
+
+ @Override
+ public void clear() {
+ mRecipeCache.clear();
+ }
+
+ @Override
+ public boolean contains(Object arg0) {
+ return mRecipeCache.containsValue((GT_Recipe) arg0);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> arg0) {
+ int a = 0;
+ for (Object v : arg0) {
+ if (this.mRecipeCache.containsValue((GT_Recipe) v)) {
+ a++;
+ }
+ }
+ return a == arg0.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mRecipeCache.isEmpty();
+ }
+
+ @Override
+ public Iterator<GT_Recipe> iterator() {
+ return mRecipeCache.iterator();
+ }
+
+ @Override
+ public boolean remove(Object arg0) {
+ return mRecipeCache.remove((GT_Recipe) arg0);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> arg0) {
+ int a = 0;
+ for (Object v : arg0) {
+ if (this.mRecipeCache.containsValue((GT_Recipe) v)) {
+ this.mRecipeCache.remove((GT_Recipe) v);
+ a++;
+ }
+ }
+ return a > 0;
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> arg0) {
+ int mStartSize = this.mRecipeCache.size();
+ this.mRecipeCache = (AutoMap<GT_Recipe>) arg0;
+ int mEndsize = this.mRecipeCache.size();
+ return mStartSize != mEndsize;
+ }
+
+ @Override
+ public int size() {
+ return this.mRecipeCache.size();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return this.mRecipeCache.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] arg0) {
+ return (T[]) this.mRecipeCache.toArray();
+ }
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/SafeTexture.java b/src/main/java/gtPlusPlus/api/objects/minecraft/SafeTexture.java
new file mode 100644
index 0000000000..7c418b5a77
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/SafeTexture.java
@@ -0,0 +1,64 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import java.util.HashMap;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gtPlusPlus.core.util.Utils;
+import net.minecraft.util.IIcon;
+
+/**
+ * A Server Side safe object that can hold {@link IIcon}s.
+ * @author Alkalus
+ *
+ */
+public class SafeTexture implements Runnable {
+
+ @SideOnly(Side.CLIENT)
+ private static final HashMap<Integer, IIcon> mHashToIconCache = new HashMap<Integer, IIcon>();
+
+ @SideOnly(Side.CLIENT)
+ private static final HashMap<String, Integer> mPathToHashCash = new HashMap<String, Integer>();
+
+ private static final HashMap<String, SafeTexture> mTextureObjectCache = new HashMap<String, SafeTexture>();
+
+ private final int mHash;
+
+ private final String mTextureName;
+
+ private final static String getKey(String aTexPath) {
+ String aNameKey = Utils.sanitizeString(aTexPath);
+ aNameKey = aNameKey.replace('/', ' ');
+ aNameKey = aNameKey.toLowerCase();
+ return aNameKey;
+ }
+
+ public static SafeTexture register(String aTexturePath) {
+ String aNameKey = getKey(aTexturePath);
+ SafeTexture g = mTextureObjectCache.get(aNameKey);
+ if (g == null) {
+ g = new SafeTexture(aTexturePath);
+ mTextureObjectCache.put(aNameKey, g);
+ mPathToHashCash.put(aTexturePath, aTexturePath.hashCode());
+ }
+ return g;
+ }
+
+ private SafeTexture(String aTexturePath) {
+ mTextureName = aTexturePath;
+ mHash = getKey(aTexturePath).hashCode();
+ GregTech_API.sGTBlockIconload.add(this);
+ }
+
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon() {
+ return mHashToIconCache.get(mHash);
+ }
+
+ @Override
+ public void run() {
+ mHashToIconCache.put(getKey(mTextureName).hashCode(), GregTech_API.sBlockIcons.registerIcon(mTextureName));
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/ShapedRecipe.java b/src/main/java/gtPlusPlus/api/objects/minecraft/ShapedRecipe.java
new file mode 100644
index 0000000000..c0e9b20c54
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/ShapedRecipe.java
@@ -0,0 +1,250 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.api.objects.data.Pair;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.oredict.ShapedOreRecipe;
+
+public class ShapedRecipe {
+
+ private final static String CHARS = "abcdefghijklmnop";
+ public ShapedOreRecipe mRecipe;
+
+ ItemStack[] mBlackList = null;
+
+ public ShapedRecipe(
+ Object aInput1, Object aInput2, Object aInput3,
+ Object aInput4, Object aInput5, Object aInput6,
+ Object aInput7, Object aInput8, Object aInput9,
+ ItemStack aOutput) {
+
+ this(new Object[] {aInput1, aInput2, aInput3, aInput4, aInput5, aInput6, aInput7, aInput8, aInput9}, aOutput);
+
+ }
+
+ public ShapedRecipe(Object[] aInputs, ItemStack aOutput) {
+ String aGridWhole = "";
+ String aGrid[] = new String[3];
+ char[] aChar = new char[9];
+ String[] aLoggingInfo = new String[9];
+
+ if (mBlackList == null) {
+ mBlackList = new ItemStack[] {};
+ }
+
+ //Just to be safe
+ try {
+ int xSlot = 0;
+ int xNull = 0;
+ for (Object u : aInputs) {
+ String mInfo = "";
+ if (u instanceof String) {
+ mInfo = (String) u;
+ Logger.RECIPE("Input slot "+xSlot+++" contains "+mInfo);
+ }
+ else if (u instanceof ItemStack || u instanceof Item) {
+ if (u instanceof Item) {
+ u = ItemUtils.getSimpleStack((Item) u);
+ }
+ mInfo = ((ItemStack) u).getDisplayName();
+ Logger.RECIPE("Input slot "+xSlot+++" contains "+mInfo);
+ }
+ else if (u == null) {
+ xNull++;
+ }
+ }
+ Logger.RECIPE("Found "+xNull+" null inputs.");
+ //Check if the output is invalid
+ if (aOutput != null && xNull < 9) {
+
+ for (ItemStack q : mBlackList) {
+ if (q != null) {
+ if (q.isItemEqual(aOutput)) {
+ Logger.RECIPE("Found recipe Alkalus is Debugging.");
+ }
+ }
+ }
+
+ Object[] mVarags2 = null;
+ Logger.RECIPE("Generating Shaped Crafting Recipe for "+aOutput.getDisplayName());
+
+ if (aInputs.length < 9 || aInputs.length > 9) {
+ Logger.RECIPE("[Fix] Recipe for "+aOutput.getDisplayName()+" has incorrect number of inputs. Size: "+aInputs.length+".");
+ //Logger.RECIPE("[1234abcd] Reciped exists at location: "+ReflectionUtils.getMethodName(1));
+ //Logger.RECIPE("[1234abcd] Reciped exists at location: "+ReflectionUtils.getMethodName(2));
+ //Logger.RECIPE("[1234abcd] Reciped exists at location: "+ReflectionUtils.getMethodName(3));
+ //Logger.RECIPE("[1234abcd] Reciped exists at location: "+ReflectionUtils.getMethodName(4));
+ //Logger.RECIPE("Reciped exists at location: "+ReflectionUtils.getMethodName(1));
+ }
+
+
+ //Build a Pair for each slot
+ AutoMap<Pair<Character, Object>> aRecipePairs = new AutoMap<Pair<Character, Object>>();
+ int aCharSlot = 0;
+ int aMemSlot = 0;
+ int aInfoSlot = 0;
+ for (Object stack : aInputs) {
+ if (stack != null) {
+ String mInfo = "";
+ if (stack instanceof String) {
+ mInfo = (String) stack;
+ }
+ else if (stack instanceof ItemStack || stack instanceof Item) {
+ if (stack instanceof Item) {
+ stack = ItemUtils.getSimpleStack((Item) stack);
+ }
+ mInfo = ((ItemStack) stack).getDisplayName();
+ }
+ aRecipePairs.put(new Pair<Character, Object>(CHARS.charAt(aCharSlot), stack));
+ Logger.RECIPE("Storing '"+CHARS.charAt(aCharSlot)+"' with an object of type "+stack.getClass().getSimpleName()+" and a value of "+mInfo);
+ aChar[aMemSlot++] = CHARS.charAt(aCharSlot);
+ aCharSlot++;
+ aLoggingInfo[aInfoSlot++] = mInfo;
+ }
+ else {
+ aRecipePairs.put(new Pair<Character, Object>(' ', (ItemStack) null));
+ Logger.RECIPE("Storing ' ' with an object of type null");
+ aChar[aMemSlot++] = ' ';
+ aLoggingInfo[aInfoSlot++] = "Empty";
+ }
+ }
+
+ Logger.RECIPE(aRecipePairs.size()+" Char|Object pairs registered for recipe.");
+ //If we have enough valid slots, iterate them and build a String which represents the entire grid.
+ //If this String is the correct length, we will split it into thirds and build the grid String array.
+ if (aRecipePairs.size() == 9) {
+
+ for (Pair<Character, Object> h : aRecipePairs) {
+ if (h.getKey() != null) {
+ aGridWhole += String.valueOf(h.getKey());
+ Logger.RECIPE("Adding '"+String.valueOf(h.getKey())+"' to aGridWhole.");
+ }
+ }
+
+ Logger.RECIPE("aGridWhole: "+aGridWhole+" | size: "+aGridWhole.length());
+
+ //Build crafting grid
+ if (aGridWhole.length() == 9) {
+ Logger.RECIPE("aGridWhole size == 9");
+ aGrid[0] = ""+aGridWhole.charAt(0)+aGridWhole.charAt(1)+aGridWhole.charAt(2);
+ aGrid[1] = ""+aGridWhole.charAt(3)+aGridWhole.charAt(4)+aGridWhole.charAt(5);
+ aGrid[2] = ""+aGridWhole.charAt(6)+aGridWhole.charAt(7)+aGridWhole.charAt(8);
+ }
+ else {
+ Logger.RECIPE("[Fix] Grid length for recipe outputting "+aOutput.getDisplayName()+" is not 9.");
+ }
+
+ //Rebuild the Map without spaces
+ aRecipePairs.clear();
+ aCharSlot = 0;
+
+ //The amount of spaces in the Varags that the Shape strings takes.
+ //Currently they are inserted as a single array into index 0.
+ final int KEY_COUNTER = 1;
+
+ int counter = KEY_COUNTER;
+ for (Object stack : aInputs) {
+ if (stack != null) {
+ String mInfo = "";
+ if (stack instanceof String) {
+ mInfo = (String) stack;
+ }
+ else if (stack instanceof ItemStack || stack instanceof Item) {
+ if (stack instanceof Item) {
+ stack = ItemUtils.getSimpleStack((Item) stack);
+ }
+ mInfo = ((ItemStack) stack).getDisplayName();
+ }
+ aRecipePairs.put(new Pair<Character, Object>(CHARS.charAt(aCharSlot), stack));
+ Logger.RECIPE("Registering Pair of '"+CHARS.charAt(aCharSlot)+"' and a "+stack.getClass().getSimpleName()+" object. Object has a value of "+mInfo);
+ aCharSlot++;
+ counter++;
+ }
+ }
+
+ Logger.RECIPE("Counter started at "+KEY_COUNTER+", counter is now at "+counter+". Trying to create Varag array with a size of "+(KEY_COUNTER+(counter-KEY_COUNTER)*2));
+ //Counter started at 3, counter is now at 4. Trying to create Varag array with a size of 2
+
+ //Register the shaped grid straight to the varags
+ mVarags2 = new Object[(KEY_COUNTER+(counter-KEY_COUNTER)*2)];
+ /*mVarags2[0] = aGrid[0];
+ mVarags2[1] = aGrid[1];
+ mVarags2[2] = aGrid[2];*/
+ mVarags2[0] = aGrid;
+
+ //Add Each Char, then Item to the varags, sequentially.
+ int counter2 = KEY_COUNTER;
+ for (Pair<Character, Object> r : aRecipePairs) {
+ char c = r.getKey();
+ Object o = r.getValue();
+
+ if (o instanceof ItemStack || o instanceof Item) {
+ if (o instanceof Item) {
+ o = ItemUtils.getSimpleStack((Item) o);
+ }
+ o = ((ItemStack) o).copy();
+ }
+
+ mVarags2[counter2] = (char) c;
+ mVarags2[counter2+1] = o;
+ counter2 += 2;
+ }
+
+ Logger.RECIPE("Recipe Summary");
+ Logger.RECIPE("+ = + = + = +");
+ Logger.RECIPE("= "+aChar[0]+" = "+aChar[1]+" = "+aChar[2]+" =");
+ Logger.RECIPE("+ = + = + = +");
+ Logger.RECIPE("= "+aChar[3]+" = "+aChar[4]+" = "+aChar[5]+" =");
+ Logger.RECIPE("+ = + = + = +");
+ Logger.RECIPE("= "+aChar[6]+" = "+aChar[7]+" = "+aChar[8]+" =");
+ Logger.RECIPE("+ = + = + = +");
+ for (int r=0;r<9;r++) {
+ if (aChar[r] != ' ') {
+ Logger.RECIPE(""+aChar[r]+" : "+aLoggingInfo[r]);
+ }
+ }
+
+ }
+ else {
+ Logger.RECIPE("[Fix] Recipe for "+aOutput.getDisplayName()+" contains a strange number of inputs.");
+ }
+
+ //Try set the recipe for this object.
+ ShapedOreRecipe testRecipe = null;
+ try {
+ testRecipe = new ShapedOreRecipe(aOutput, mVarags2);
+ }
+ catch (Throwable t) {
+ Logger.RECIPE("[Fix][0] Error thrown when making a ShapedOreRecipe object.");
+ t.printStackTrace();
+ }
+ if (testRecipe == null) {
+ this.mRecipe = null;
+ Logger.RECIPE("[Fix] Failed to generate a shaped recipe.");
+ }
+ else {
+ this.mRecipe = testRecipe;
+ Logger.RECIPE("Generated a shaped recipe successfully.");
+ }
+ }
+
+ //Output was not valid
+ else {
+ this.mRecipe = null;
+ Logger.RECIPE("[Fix] Failed to generate a shaped recipe. Output was not valid.");
+ }
+
+
+ }
+ catch(Throwable t) {
+ this.mRecipe = null;
+ Logger.RECIPE("[Fix][1] Error thrown when making a ShapedOreRecipe object.");
+ t.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/TexturePackage.java b/src/main/java/gtPlusPlus/api/objects/minecraft/TexturePackage.java
new file mode 100644
index 0000000000..e610f8fdf0
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/TexturePackage.java
@@ -0,0 +1,55 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import java.util.LinkedHashMap;
+import java.util.Set;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+import net.minecraft.util.IIcon;
+
+public class TexturePackage {
+
+ private AutoMap<IIcon> mAnimationArray = new AutoMap<IIcon>();
+
+ public IIcon getFrame(int aFrame) {
+ if (aFrame < 0 || aFrame >= mAnimationArray.size()) {
+ return mAnimationArray.get(0);
+ }
+ return mAnimationArray.get(aFrame);
+ }
+
+ public boolean addFrame(IIcon aFrame) {
+ if (aFrame != null) {
+ return mAnimationArray.add(aFrame);
+ }
+ return false;
+ }
+
+ public boolean addFrames(AutoMap<IIcon> aFrames) {
+ for (IIcon h : aFrames) {
+ if (!addFrame(h)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean addFrames(LinkedHashMap<?, IIcon> aFrames) {
+ for (IIcon h : aFrames.values()) {
+ if (!addFrame(h)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean addFrames(Set<IIcon> aFrames) {
+ for (IIcon h : aFrames) {
+ if (!addFrame(h)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/ThreadPooCollector.java b/src/main/java/gtPlusPlus/api/objects/minecraft/ThreadPooCollector.java
new file mode 100644
index 0000000000..0ff6e112ac
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/ThreadPooCollector.java
@@ -0,0 +1,111 @@
+package gtPlusPlus.api.objects.minecraft;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import gtPlusPlus.GTplusplus;
+import gtPlusPlus.GTplusplus.INIT_PHASE;
+import gtPlusPlus.api.objects.data.Pair;
+import gtPlusPlus.core.tileentities.machines.TileEntityPooCollector;
+import gtPlusPlus.core.util.Utils;
+import net.minecraft.entity.passive.EntityAnimal;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+
+public class ThreadPooCollector extends Thread {
+
+ public boolean canRun = true;
+ public boolean isRunning = false;
+
+ private static final long INIT_TIME;
+ private static long internalTickCounter = 0;
+
+ private static final ThreadPooCollector mThread;
+ private static final HashMap<String, Pair<BlockPos, TileEntityPooCollector>> mPooCollectors = new LinkedHashMap<String, Pair<BlockPos, TileEntityPooCollector>>();
+
+
+ static {
+ mThread = new ThreadPooCollector();
+ INIT_TIME = (System.currentTimeMillis());
+ }
+
+ public ThreadPooCollector() {
+ setName("gtpp.handler.poop");
+ start();
+ }
+
+ public static ThreadPooCollector getInstance() {
+ return mThread;
+ }
+
+ public static void addTask(TileEntityPooCollector aTile) {
+ BlockPos aTempPos = new BlockPos(aTile);
+ mPooCollectors.put(aTempPos.getUniqueIdentifier(), new Pair<BlockPos, TileEntityPooCollector>(aTempPos, aTile));
+ }
+
+ public static void stopThread() {
+ mThread.canRun = false;
+ }
+
+
+ @Override
+ public void run() {
+
+ if (!isRunning) {
+ isRunning = true;
+ }
+ else {
+ return;
+ }
+
+ while (canRun) {
+ if (mPooCollectors.isEmpty() || GTplusplus.CURRENT_LOAD_PHASE != INIT_PHASE.STARTED) {
+ continue;
+ } else {
+ internalTickCounter = Utils.getTicksFromSeconds(
+ Utils.getSecondsFromMillis(Utils.getMillisSince(INIT_TIME, System.currentTimeMillis())));
+ if (internalTickCounter % 100 == 0) {
+ for (Pair<BlockPos, TileEntityPooCollector> pair : mPooCollectors.values()) {
+ if (pair != null) {
+ BlockPos p = pair.getKey();
+ if (p != null) {
+ if (p.world != null) {
+ World w = p.world;
+ if (w == null) {
+ continue;
+ }
+ Chunk c = w.getChunkFromBlockCoords(p.xPos, p.zPos);
+ if (c != null) {
+ if (c.isChunkLoaded) {
+ int startX = p.xPos - 2;
+ int startY = p.yPos;
+ int startZ = p.zPos - 2;
+ int endX = p.xPos + 3;
+ int endY = p.yPos + 5;
+ int endZ = p.zPos + 3;
+ AxisAlignedBB box = AxisAlignedBB.getBoundingBox(startX, startY, startZ,
+ endX, endY, endZ);
+ if (box != null) {
+ @SuppressWarnings("unchecked")
+ List<EntityAnimal> animals = w.getEntitiesWithinAABB(EntityAnimal.class, box);
+ if (animals != null && !animals.isEmpty()) {
+ pair.getValue().onPostTick(animals);
+ }
+ } else {
+ continue;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoEUBonusMultiBehaviour.java b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoEUBonusMultiBehaviour.java
new file mode 100644
index 0000000000..78341db7a1
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoEUBonusMultiBehaviour.java
@@ -0,0 +1,27 @@
+package gtPlusPlus.api.objects.minecraft.multi;
+
+import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList;
+import net.minecraft.item.ItemStack;
+
+public class NoEUBonusMultiBehaviour extends SpecialMultiBehaviour {
+
+ public NoEUBonusMultiBehaviour() {
+ // Used by other mods which may wish to not obtain bonus outputs on their Sifting or Maceration recipes.
+ }
+
+ @Override
+ public ItemStack getTriggerItem() {
+ return GregtechItemList.Chip_MultiNerf_NoEuBonus.get(1);
+ }
+
+ @Override
+ public String getTriggerItemTooltip() {
+ return "Prevents EU discounts on GT++ multiblocks when used";
+ }
+
+ @Override
+ public int getEUPercent() {
+ return 0;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoOutputBonusMultiBehaviour.java b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoOutputBonusMultiBehaviour.java
new file mode 100644
index 0000000000..8137f2573d
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoOutputBonusMultiBehaviour.java
@@ -0,0 +1,27 @@
+package gtPlusPlus.api.objects.minecraft.multi;
+
+import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList;
+import net.minecraft.item.ItemStack;
+
+public class NoOutputBonusMultiBehaviour extends SpecialMultiBehaviour {
+
+ public NoOutputBonusMultiBehaviour() {
+ // Used by other mods which may wish to not obtain bonus outputs on their Sifting or Maceration recipes.
+ }
+
+ @Override
+ public ItemStack getTriggerItem() {
+ return GregtechItemList.Chip_MultiNerf_NoOutputBonus.get(1);
+ }
+
+ @Override
+ public String getTriggerItemTooltip() {
+ return "Prevents bonus output % on GT++ multiblocks when used";
+ }
+
+ @Override
+ public int getOutputChanceRoll() {
+ return 10000;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoSpeedBonusMultiBehaviour.java b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoSpeedBonusMultiBehaviour.java
new file mode 100644
index 0000000000..fe7a90960d
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoSpeedBonusMultiBehaviour.java
@@ -0,0 +1,27 @@
+package gtPlusPlus.api.objects.minecraft.multi;
+
+import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList;
+import net.minecraft.item.ItemStack;
+
+public class NoSpeedBonusMultiBehaviour extends SpecialMultiBehaviour {
+
+ public NoSpeedBonusMultiBehaviour() {
+ // Used by other mods which may wish to not obtain bonus outputs on their Sifting or Maceration recipes.
+ }
+
+ @Override
+ public ItemStack getTriggerItem() {
+ return GregtechItemList.Chip_MultiNerf_NoSpeedBonus.get(1);
+ }
+
+ @Override
+ public String getTriggerItemTooltip() {
+ return "Prevents speed bonuses on GT++ multiblocks when used";
+ }
+
+ @Override
+ public int getSpeedBonusPercent() {
+ return 0;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/multi/SpecialMultiBehaviour.java b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/SpecialMultiBehaviour.java
new file mode 100644
index 0000000000..e562ccc40b
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/SpecialMultiBehaviour.java
@@ -0,0 +1,44 @@
+package gtPlusPlus.api.objects.minecraft.multi;
+
+import gregtech.api.util.GT_Utility;
+import net.minecraft.item.ItemStack;
+
+/**
+ * Extend this class to implement custom behaviour for multiblocks.
+ * The Trigger item when in a special slot or input bus, will cause the multiblock to behave as specified.
+ * Not overriding a method here will cause the default values to be used.
+ * @author Alkalus
+ *
+ */
+public abstract class SpecialMultiBehaviour {
+
+ private final int mMaxParallelRecipes = Short.MIN_VALUE;
+ private final int mEUPercent = Short.MIN_VALUE;
+ private final int mSpeedBonusPercent = Short.MIN_VALUE;
+ private final int mOutputChanceRoll = Short.MIN_VALUE;
+
+ public abstract ItemStack getTriggerItem();
+
+ public abstract String getTriggerItemTooltip();
+
+ public int getMaxParallelRecipes() {
+ return this.mMaxParallelRecipes;
+ }
+
+ public int getEUPercent() {
+ return this.mEUPercent;
+ }
+
+ public int getSpeedBonusPercent() {
+ return this.mSpeedBonusPercent;
+ }
+
+ public int getOutputChanceRoll() {
+ return this.mOutputChanceRoll;
+ }
+
+ public final boolean isTriggerItem(ItemStack aToMatch) {
+ return GT_Utility.areStacksEqual(getTriggerItem(), aToMatch, false);
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/random/CSPRNG_DO_NOT_USE.java b/src/main/java/gtPlusPlus/api/objects/random/CSPRNG_DO_NOT_USE.java
new file mode 100644
index 0000000000..b2dc984456
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/random/CSPRNG_DO_NOT_USE.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2005, Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of the modp.com nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This is the standard "new" BSD license:
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+
+package gtPlusPlus.api.objects.random;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Random;
+
+import gtPlusPlus.api.interfaces.IRandomGenerator;
+import gtPlusPlus.core.util.Utils;
+
+/**
+ * The Blum-Blum-Shub random number generator.
+ *
+ * <p>
+ * The Blum-Blum-Shub is a "cryptographically secure" random number
+ * generator. It has been proven that predicting the ouput
+ * is equivalent to factoring <i>n</i>, a large integer generated
+ * from two prime numbers.
+ * </p>
+ *
+ * <p>
+ * The Algorithm:
+ * </p>
+ * <ol>
+ * <li>
+ * (setup) generate two secret prime numbers <i>p</i>, <i>q</i> such that
+ * <i>p</i> &ne; <i>q</i>, <i>p</i> &equiv; 3 mod 4, <i>q</i> &equiv; 3 mod 4.
+ * </li>
+ * <li> (setup) compute <i>n</i> = <i>pq</i>. <i>n</i> can be re-used, but
+ * <i>p</i>, and <i>q</i> are secret and should be disposed of.</li>
+ * <li> Generate a (secure) random seed <i>s</i> in the range [1, <i>n</i> -1]
+ * such that gcd(<i>s</i>, <i>n</i>) = 1.
+ * <li> Compute <i>x</i> = <i>s</i><sup>2</sup> mod <i>n</i></li>
+ * <li> Compute a single random bit with:
+ * <ol>
+ * <li> <i>x</i> = <i>x</i><sup>2</sup> mod <i>n</i></li>
+ * <li> return Least-Significant-Bit(<i>x</i>) (i.e. <i>x</i> & 1)</li>
+ * </ol>
+ * Repeat as necessary.
+ * </li>
+ * </ol>
+ *
+ * <p>
+ * The code originally appeared in <a href="http://modp.com/cida/"><i>Cryptography for
+ * Internet and Database Applications </i>, Chapter 4, pages 174-177</a>
+ * </p>
+ * <p>
+ * More details are in the <a href="http://www.cacr.math.uwaterloo.ca/hac/"><i>Handbook of Applied Cryptography</i></a>,
+ * <a href="http://www.cacr.math.uwaterloo.ca/hac/about/chap5.pdf">Section 5.5.2</a>
+ * </p>
+ *
+ * @author Nick Galbreath -- nickg [at] modp [dot] com
+ * @version 3 -- 06-Jul-2005
+ *
+ */
+public class CSPRNG_DO_NOT_USE extends Random implements IRandomGenerator {
+
+ // pre-compute a few values
+ private static final BigInteger two = BigInteger.valueOf(2L);
+
+ private static final BigInteger three = BigInteger.valueOf(3L);
+
+ private static final BigInteger four = BigInteger.valueOf(4L);
+
+ /**
+ * main parameter
+ */
+ private BigInteger n;
+
+ private BigInteger state;
+
+ /**
+ * Generate appropriate prime number for use in Blum-Blum-Shub.
+ *
+ * This generates the appropriate primes (p = 3 mod 4) needed to compute the
+ * "n-value" for Blum-Blum-Shub.
+ *
+ * @param bits Number of bits in prime
+ * @param rand A source of randomness
+ */
+ private static BigInteger getPrime(int bits, Random rand) {
+ BigInteger p;
+ while (true) {
+ p = new BigInteger(bits, 100, rand);
+ if (p.mod(four).equals(three))
+ break;
+ }
+ return p;
+ }
+
+ /**
+ * This generates the "n value" -- the multiplication of two equally sized
+ * random prime numbers -- for use in the Blum-Blum-Shub algorithm.
+ *
+ * @param bits
+ * The number of bits of security
+ * @param rand
+ * A random instance to aid in generating primes
+ * @return A BigInteger, the <i>n</i>.
+ */
+ public static BigInteger generateN(int bits, Random rand) {
+ BigInteger p = getPrime(bits/2, rand);
+ BigInteger q = getPrime(bits/2, rand);
+
+ // make sure p != q (almost always true, but just in case, check)
+ while (p.equals(q)) {
+ q = getPrime(bits, rand);
+ }
+ return p.multiply(q);
+ }
+
+ /**
+ * Constructor, specifing bits for <i>n</i>
+ *
+ * @param bits number of bits
+ */
+ public CSPRNG_DO_NOT_USE(int bits) {
+ this(bits, new Random());
+ }
+
+ /**
+ * Constructor, generates prime and seed
+ *
+ * @param bits
+ * @param rand
+ */
+ public CSPRNG_DO_NOT_USE(int bits, Random rand) {
+ this(generateN(bits, rand));
+ }
+
+ /**
+ * A constructor to specify the "n-value" to the Blum-Blum-Shub algorithm.
+ * The inital seed is computed using Java's internal "true" random number
+ * generator.
+ *
+ * @param n
+ * The n-value.
+ */
+ public CSPRNG_DO_NOT_USE(BigInteger n) {
+ this(n, SecureRandom.getSeed(n.bitLength() / 8));
+ }
+
+ /**
+ * A constructor to specify both the n-value and the seed to the
+ * Blum-Blum-Shub algorithm.
+ *
+ * @param n
+ * The n-value using a BigInteger
+ * @param seed
+ * The seed value using a byte[] array.
+ */
+ public CSPRNG_DO_NOT_USE(BigInteger n, byte[] seed) {
+ this.n = n;
+ setSeed(seed);
+ }
+
+ /**
+ * Sets or resets the seed value and internal state
+ *
+ * @param seedBytes
+ * The new seed.
+ */
+ public void setSeed(byte[] seedBytes) {
+ // ADD: use hardwired default for n
+ BigInteger seed = new BigInteger(1, seedBytes);
+ state = seed.mod(n);
+ }
+
+ /**
+ * Returns up to numBit random bits
+ *
+ * @return int
+ */
+ @Override
+ public int next(int numBits) {
+ // TODO: find out how many LSB one can extract per cycle.
+ // it is more than one.
+ int result = 0;
+ for (int i = numBits; i != 0; --i) {
+ state = state.modPow(two, n);
+ result = (result << 1) | (state.testBit(0) == true ? 1 : 0);
+ }
+ return result;
+ }
+
+
+ public static CSPRNG_DO_NOT_USE generate(){
+ return generate(512);
+ }
+
+ /**
+ * @return CSPRNG_DO_NOT_USE
+ * @Author Draknyte1/Alkalus
+ */
+ public static CSPRNG_DO_NOT_USE generate(int bitsize){
+ // First use the internal, stock "true" random number
+ // generator to get a "true random seed"
+ SecureRandom r = Utils.generateSecureRandom();
+ r.nextInt(); // need to do something for SR to be triggered.
+ // Use this seed to generate a n-value for Blum-Blum-Shub
+ // This value can be re-used if desired.
+ BigInteger nval = CSPRNG_DO_NOT_USE.generateN(bitsize, r);
+ // now get a seed
+ byte[] seed = new byte[bitsize/8];
+ r.nextBytes(seed);
+ // now create an instance of BlumBlumShub
+ CSPRNG_DO_NOT_USE bbs = new CSPRNG_DO_NOT_USE(nval, seed);
+ return bbs;
+ }
+
+
+ /**
+ * @return CSPRNG_DO_NOT_USE
+ * @Author Draknyte1/Alkalus
+ */
+ public static CSPRNG_DO_NOT_USE generate(Random aRandom){
+ return generate(512, aRandom);
+ }
+
+ /**
+ * @return CSPRNG_DO_NOT_USE
+ * @Author Draknyte1/Alkalus
+ */
+ public static CSPRNG_DO_NOT_USE generate(int aBitSize, Random aRandom){
+ // First use the internal, stock "true" random number
+ // generator to get a "true random seed"
+ SecureRandom r = Utils.generateSecureRandom();
+ r.nextInt(); // need to do something for SR to be triggered.
+ // Use this seed to generate a n-value for Blum-Blum-Shub
+ // This value can be re-used if desired.
+ int bitsize = aBitSize;
+ // now create an instance of BlumBlumShub
+ // do everything almost automatically
+ CSPRNG_DO_NOT_USE bbs = new CSPRNG_DO_NOT_USE(bitsize, aRandom);
+ return bbs;
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/objects/random/UUIDGenerator.java b/src/main/java/gtPlusPlus/api/objects/random/UUIDGenerator.java
new file mode 100644
index 0000000000..fec92368f8
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/random/UUIDGenerator.java
@@ -0,0 +1,449 @@
+package gtPlusPlus.api.objects.random;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.Random;
+import java.util.UUID;
+
+/**
+ *
+ * Implement modified version of Apache's OpenJPA UUID generator.
+ * This UUID generator is paired with a Blum-Blum-Shub random number generator
+ * which in itself is seeded by custom SecureRandom.
+ *
+ * The UUID generator class has been converted from a static factory to an instanced factory.
+ *
+ */
+
+//========================================= APACHE BLOCK =========================================
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * UUID value generator. Type 1 generator is based on the time-based generator
+ * in the Apache Commons Id project: http://jakarta.apache.org/commons/sandbox
+ * /id/uuid.html The type 4 generator uses the standard Java UUID generator.
+ *
+ * The type 1 code has been vastly simplified and modified to replace the
+ * ethernet address of the host machine with the IP, since we do not want to
+ * require native libs and Java cannot access the MAC address directly.
+ *
+ * In spirit, implements the IETF UUID draft specification, found here:<br />
+ * http://www1.ics.uci.edu/~ejw/authoring/uuid-guid/draft-leach-uuids-guids-01
+ * .txt
+ *
+ * @author Abe White, Kevin Sutter
+ * @since 0.3.3
+ */
+public class UUIDGenerator {
+
+ // supported UUID types
+ public static final int TYPE1 = 1;
+ public static final int TYPE4 = 4;
+ // indexes within the uuid array for certain boundaries
+ private static final byte IDX_TIME_HI = 6;
+ private static final byte IDX_TYPE = 6; // multiplexed
+ private static final byte IDX_TIME_MID = 4;
+ private static final byte IDX_TIME_LO = 0;
+ private static final byte IDX_TIME_SEQ = 8;
+ private static final byte IDX_VARIATION = 8; // multiplexed
+ // indexes and lengths within the timestamp for certain boundaries
+ private static final byte TS_TIME_LO_IDX = 4;
+ private static final byte TS_TIME_LO_LEN = 4;
+ private static final byte TS_TIME_MID_IDX = 2;
+ private static final byte TS_TIME_MID_LEN = 2;
+ private static final byte TS_TIME_HI_IDX = 0;
+ private static final byte TS_TIME_HI_LEN = 2;
+ // offset to move from 1/1/1970, which is 0-time for Java, to gregorian
+ // 0-time 10/15/1582, and multiplier to go from 100nsec to msec units
+ private static final long GREG_OFFSET = 0xB1D069B5400L;
+ private static final long MILLI_MULT = 10000L;
+ // type of UUID -- time based
+ private final static byte TYPE_TIME_BASED = 0x10;
+ // random number generator used to reduce conflicts with other JVMs, and
+ // hasher for strings.
+ private Random RANDOM;
+ // 4-byte IP address + 2 random bytes to compensate for the fact that
+ // the MAC address is usually 6 bytes
+ private byte[] IP;
+ // counter is initialized to 0 and is incremented for each uuid request
+ // within the same timestamp window.
+ private int _counter;
+ // current timestamp (used to detect multiple uuid requests within same
+ // timestamp)
+ private long _currentMillis;
+ // last used millis time, and a semi-random sequence that gets reset
+ // when it overflows
+ private long _lastMillis = 0L;
+ private static final int MAX_14BIT = 0x3FFF;
+ private short _seq = 0;
+ private boolean type1Initialized = false; /*
+ * Initializer for type 1 UUIDs. Creates random generator and genenerates
+ * the node portion of the UUID using the IP address.
+ */
+ private synchronized void initializeForType1() {
+ if (type1Initialized == true) {
+ return;
+ }
+ // note that secure random is very slow the first time
+ // it is used; consider switching to a standard random
+ RANDOM = CSPRNG_DO_NOT_USE.generate();
+ _seq = (short) RANDOM.nextInt(MAX_14BIT);
+
+ byte[] ip = null;
+ try {
+ ip = InetAddress.getLocalHost().getAddress();
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ IP = new byte[6];
+ RANDOM.nextBytes(IP);
+ //OPENJPA-2055: account for the fact that 'getAddress'
+ //may return an IPv6 address which is 16 bytes wide.
+ for( int i = 0 ; i < ip.length; ++i ) {
+ IP[2+(i%4)] ^= ip[i];
+ }
+ type1Initialized = true;
+ }
+ /**
+ * Return a unique UUID value.
+ */
+ public byte[] next(int type) {
+ if (type == TYPE4) {
+ return createType4();
+ }
+ return createType1();
+ }
+ /*
+ * Creates a type 1 UUID
+ */
+ public byte[] createType1() {
+ if (type1Initialized == false) {
+ initializeForType1();
+ }
+ // set ip addr
+ byte[] uuid = new byte[16];
+ System.arraycopy(IP, 0, uuid, 10, IP.length);
+ // Set time info. Have to do this processing within a synchronized
+ // block because of the statics...
+ long now = 0;
+ synchronized (UUIDGenerator.class) {
+ // Get the time to use for this uuid. This method has the side
+ // effect of modifying the clock sequence, as well.
+ now = getTime();
+ // Insert the resulting clock sequence into the uuid
+ uuid[IDX_TIME_SEQ] = (byte) ((_seq & 0x3F00) >>> 8);
+ uuid[IDX_VARIATION] |= 0x80;
+ uuid[IDX_TIME_SEQ+1] = (byte) (_seq & 0xFF);
+ }
+ // have to break up time because bytes are spread through uuid
+ byte[] timeBytes = Bytes.toBytes(now);
+ // Copy time low
+ System.arraycopy(timeBytes, TS_TIME_LO_IDX, uuid, IDX_TIME_LO,
+ TS_TIME_LO_LEN);
+ // Copy time mid
+ System.arraycopy(timeBytes, TS_TIME_MID_IDX, uuid, IDX_TIME_MID,
+ TS_TIME_MID_LEN);
+ // Copy time hi
+ System.arraycopy(timeBytes, TS_TIME_HI_IDX, uuid, IDX_TIME_HI,
+ TS_TIME_HI_LEN);
+ //Set version (time-based)
+ uuid[IDX_TYPE] |= TYPE_TIME_BASED; // 0001 0000
+ return uuid;
+ }
+ /*
+ * Creates a type 4 UUID
+ */
+ private byte[] createType4() {
+ UUID type4 = UUID.randomUUID();
+ byte[] uuid = new byte[16];
+ longToBytes(type4.getMostSignificantBits(), uuid, 0);
+ longToBytes(type4.getLeastSignificantBits(), uuid, 8);
+ return uuid;
+ }
+ /*
+ * Converts a long to byte values, setting them in a byte array
+ * at a given starting position.
+ */
+ private void longToBytes(long longVal, byte[] buf, int sPos) {
+ sPos += 7;
+ for(int i = 0; i < 8; i++)
+ buf[sPos-i] = (byte)(longVal >>> (i * 8));
+ }
+
+ /**
+ * Return the next unique uuid value as a 16-character string.
+ */
+ public String nextString(int type) {
+ byte[] bytes = next(type);
+ try {
+ return new String(bytes, "ISO-8859-1");
+ } catch (Exception e) {
+ return new String(bytes);
+ }
+ }
+ /**
+ * Return the next unique uuid value as a 32-character hex string.
+ */
+ public String nextHex(int type) {
+ return Base16Encoder.encode(next(type));
+ }
+ /**
+ * Get the timestamp to be used for this uuid. Must be called from
+ * a synchronized block.
+ *
+ * @return long timestamp
+ */
+ // package-visibility for testing
+ private long getTime() {
+ if (RANDOM == null)
+ initializeForType1();
+ long newTime = getUUIDTime();
+ if (newTime <= _lastMillis) {
+ incrementSequence();
+ newTime = getUUIDTime();
+ }
+ _lastMillis = newTime;
+ return newTime;
+ }
+ /**
+ * Gets the appropriately modified timestamep for the UUID. Must be called
+ * from a synchronized block.
+ *
+ * @return long timestamp in 100ns intervals since the Gregorian change
+ * offset
+ */
+ private long getUUIDTime() {
+ if (_currentMillis != System.currentTimeMillis()) {
+ _currentMillis = System.currentTimeMillis();
+ _counter = 0; // reset counter
+ }
+ // check to see if we have created too many uuid's for this timestamp
+ if (_counter + 1 >= MILLI_MULT) {
+ // Original algorithm threw exception. Seemed like overkill.
+ // Let's just increment the timestamp instead and start over...
+ _currentMillis++;
+ _counter = 0;
+ }
+ // calculate time as current millis plus offset times 100 ns ticks
+ long currentTime = (_currentMillis + GREG_OFFSET) * MILLI_MULT;
+ // return the uuid time plus the artificial tick counter incremented
+ return currentTime + _counter++;
+ }
+ /**
+ * Increments the clock sequence for this uuid. Must be called from a
+ * synchronized block.
+ */
+ private void incrementSequence() {
+ // increment, but if it's greater than its 14-bits, reset it
+ if (++_seq > MAX_14BIT) {
+ _seq = (short) RANDOM.nextInt(MAX_14BIT); // semi-random
+ }
+ }
+
+ //Add Dependant classes internally
+
+ /**
+ * This class came from the Apache Commons Id sandbox project in support
+ * of the UUIDGenerator implementation.
+ *
+ * <p>Static methods for managing byte arrays (all methods follow Big
+ * Endian order where most significant bits are in front).</p>
+ */
+ public static final class Bytes {
+ /**
+ * <p>Hide constructor in utility class.</p>
+ */
+ private Bytes() {
+ }
+ /**
+ * Appends two bytes array into one.
+ *
+ * @param a A byte[].
+ * @param b A byte[].
+ * @return A byte[].
+ */
+ public static byte[] append(byte[] a, byte[] b) {
+ byte[] z = new byte[a.length + b.length];
+ System.arraycopy(a, 0, z, 0, a.length);
+ System.arraycopy(b, 0, z, a.length, b.length);
+ return z;
+ }
+ /**
+ * Returns a 8-byte array built from a long.
+ *
+ * @param n The number to convert.
+ * @return A byte[].
+ */
+ public static byte[] toBytes(long n) {
+ return toBytes(n, new byte[8]);
+ }
+ /**
+ * Build a 8-byte array from a long. No check is performed on the
+ * array length.
+ *
+ * @param n The number to convert.
+ * @param b The array to fill.
+ * @return A byte[].
+ */
+ public static byte[] toBytes(long n, byte[] b) {
+ b[7] = (byte) (n);
+ n >>>= 8;
+ b[6] = (byte) (n);
+ n >>>= 8;
+ b[5] = (byte) (n);
+ n >>>= 8;
+ b[4] = (byte) (n);
+ n >>>= 8;
+ b[3] = (byte) (n);
+ n >>>= 8;
+ b[2] = (byte) (n);
+ n >>>= 8;
+ b[1] = (byte) (n);
+ n >>>= 8;
+ b[0] = (byte) (n);
+
+ return b;
+ }
+ /**
+ * Build a long from first 8 bytes of the array.
+ *
+ * @param b The byte[] to convert.
+ * @return A long.
+ */
+ public static long toLong(byte[] b) {
+ return ((((long) b[7]) & 0xFF)
+ + ((((long) b[6]) & 0xFF) << 8)
+ + ((((long) b[5]) & 0xFF) << 16)
+ + ((((long) b[4]) & 0xFF) << 24)
+ + ((((long) b[3]) & 0xFF) << 32)
+ + ((((long) b[2]) & 0xFF) << 40)
+ + ((((long) b[1]) & 0xFF) << 48)
+ + ((((long) b[0]) & 0xFF) << 56));
+ }
+ /**
+ * Compares two byte arrays for equality.
+ *
+ * @param a A byte[].
+ * @param b A byte[].
+ * @return True if the arrays have identical contents.
+ */
+ public static boolean areEqual(byte[] a, byte[] b) {
+ int aLength = a.length;
+ if (aLength != b.length) {
+ return false;
+ }
+ for (int i = 0; i < aLength; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ /**
+ * <p>Compares two byte arrays as specified by <code>Comparable</code>.
+ *
+ * @param lhs - left hand value in the comparison operation.
+ * @param rhs - right hand value in the comparison operation.
+ * @return a negative integer, zero, or a positive integer as
+ * <code>lhs</code> is less than, equal to, or greater than
+ * <code>rhs</code>.
+ */
+ public static int compareTo(byte[] lhs, byte[] rhs) {
+ if (lhs == rhs) {
+ return 0;
+ }
+ if (lhs == null) {
+ return -1;
+ }
+ if (rhs == null) {
+ return +1;
+ }
+ if (lhs.length != rhs.length) {
+ return ((lhs.length < rhs.length) ? -1 : +1);
+ }
+ for (int i = 0; i < lhs.length; i++) {
+ if (lhs[i] < rhs[i]) {
+ return -1;
+ } else if (lhs[i] > rhs[i]) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+ /**
+ * Build a short from first 2 bytes of the array.
+ *
+ * @param b The byte[] to convert.
+ * @return A short.
+ */
+ public static short toShort(byte[] b) {
+ return (short) ((b[1] & 0xFF) + ((b[0] & 0xFF) << 8));
+ }
+ }
+ /**
+ * Base 16 encoder.
+ *
+ * @author Marc Prud'hommeaux
+ */
+ public static final class Base16Encoder {
+
+ private final static char[] HEX = new char[]{
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ /**
+ * Convert bytes to a base16 string.
+ */
+ public static String encode(byte[] byteArray) {
+ StringBuilder hexBuffer = new StringBuilder(byteArray.length * 2);
+ for (int i = 0; i < byteArray.length; i++)
+ for (int j = 1; j >= 0; j--)
+ hexBuffer.append(HEX[(byteArray[i] >> (j * 4)) & 0xF]);
+ return hexBuffer.toString();
+ }
+ /**
+ * Convert a base16 string into a byte array.
+ */
+ public static byte[] decode(String s) {
+ int len = s.length();
+ byte[] r = new byte[len / 2];
+ for (int i = 0; i < r.length; i++) {
+ int digit1 = s.charAt(i * 2), digit2 = s.charAt(i * 2 + 1);
+ if (digit1 >= '0' && digit1 <= '9')
+ digit1 -= '0';
+ else if (digit1 >= 'A' && digit1 <= 'F')
+ digit1 -= 'A' - 10;
+ if (digit2 >= '0' && digit2 <= '9')
+ digit2 -= '0';
+ else if (digit2 >= 'A' && digit2 <= 'F')
+ digit2 -= 'A' - 10;
+
+ r[i] = (byte) ((digit1 << 4) + digit2);
+ }
+ return r;
+ }
+ }
+
+
+
+}
+
+//========================================= APACHE BLOCK =========================================
+
diff --git a/src/main/java/gtPlusPlus/api/objects/random/XSTR.java b/src/main/java/gtPlusPlus/api/objects/random/XSTR.java
new file mode 100644
index 0000000000..6ce1cbeb6c
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/objects/random/XSTR.java
@@ -0,0 +1,278 @@
+package gtPlusPlus.api.objects.random;
+/**
+ * A subclass of java.util.random that implements the Xorshift random number
+ * generator
+ *
+ * - it is 30% faster than the generator from Java's library - it produces
+ * random sequences of higher quality than java.util.Random - this class also
+ * provides a clone() function
+ *
+ * Usage: XSRandom rand = new XSRandom(); //Instantiation x = rand.nextInt();
+ * //pull a random number
+ *
+ * To use the class in legacy code, you may also instantiate an XSRandom object
+ * and assign it to a java.util.Random object: java.util.Random rand = new
+ * XSRandom();
+ *
+ * for an explanation of the algorithm, see
+ * http://demesos.blogspot.com/2011/09/pseudo-random-number-generators.html
+ *
+ * @author Wilfried Elmenreich University of Klagenfurt/Lakeside Labs
+ * http://www.elmenreich.tk
+ *
+ * This code is released under the GNU Lesser General Public License Version 3
+ * http://www.gnu.org/licenses/lgpl-3.0.txt
+ */
+
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * XSTR - Xorshift ThermiteRandom
+ * Modified by Bogdan-G
+ * 03.06.2016
+ * version 0.0.4
+ */
+public class XSTR extends Random implements Cloneable {
+
+ private static final long serialVersionUID = 6208727693524452904L;
+ private long seed;
+ private long last;
+ private static final long GAMMA = 0x9e3779b97f4a7c15L;
+ private static final int PROBE_INCREMENT = 0x9e3779b9;
+ private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
+ private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
+ private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
+
+ /*
+ MODIFIED BY: Robotia
+ Modification: Implemented Random class seed generator
+ */
+ /**
+ * Creates a new pseudo random number generator. The seed is initialized to
+ * the current time, as if by
+ * <code>setSeed(System.currentTimeMillis());</code>.
+ */
+ public XSTR() {
+ this(seedUniquifier() ^ System.nanoTime());
+ }
+ private static final AtomicLong seedUniquifier
+ = new AtomicLong(8682522807148012L);
+
+ private static long seedUniquifier() {
+ // L'Ecuyer, "Tables of Linear Congruential Generators of
+ // Different Sizes and Good Lattice Structure", 1999
+ for (;;) {
+ final long current = seedUniquifier.get();
+ final long next = current * 181783497276652981L;
+ if (seedUniquifier.compareAndSet(current, next)) {
+ return next;
+ }
+ }
+ }
+
+ /**
+ * Creates a new pseudo random number generator, starting with the specified
+ * seed, using <code>setSeed(seed);</code>.
+ *
+ * @param seed the initial seed
+ */
+ public XSTR(final long seed) {
+ this.seed = seed;
+ }
+ @Override
+ public boolean nextBoolean() {
+ return this.next(1) != 0;
+ }
+
+ @Override
+ public double nextDouble() {
+ return (((long)(this.next(26)) << 27) + this.next(27)) * DOUBLE_UNIT;
+ }
+ /**
+ * Returns the current state of the seed, can be used to clone the object
+ *
+ * @return the current seed
+ */
+ public synchronized long getSeed() {
+ return this.seed;
+ }
+
+ /**
+ * Sets the seed for this pseudo random number generator. As described
+ * above, two instances of the same random class, starting with the same
+ * seed, produce the same results, if the same methods are called.
+ *
+ * @param seed the new seed
+ */
+ @Override
+ public synchronized void setSeed(final long seed) {
+ this.seed = seed;
+ }
+
+ /**
+ * @return Returns an XSRandom object with the same state as the original
+ */
+ @Override
+ public XSTR clone() {
+ try {
+ super.clone();
+ }
+ catch (CloneNotSupportedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return new XSTR(this.getSeed());
+ }
+
+ /**
+ * Implementation of George Marsaglia's elegant Xorshift random generator
+ * 30% faster and better quality than the built-in java.util.random see also
+ * see http://www.javamex.com/tutorials/random_numbers/xorshift.shtml
+ *
+ * @param nbits
+ * @return
+ */
+ @Override
+ public int next(final int nbits) {
+ long x = this.seed;
+ x ^= (x << 21);
+ x ^= (x >>> 35);
+ x ^= (x << 4);
+ this.seed = x;
+ x &= ((1L << nbits) - 1);
+ return (int) x;
+ }
+ boolean haveNextNextGaussian = false;
+ double nextNextGaussian = 0;
+ @Override
+ synchronized public double nextGaussian() {
+ // See Knuth, ACP, Section 3.4.1 Algorithm C.
+ if (this.haveNextNextGaussian) {
+ this.haveNextNextGaussian = false;
+ return this.nextNextGaussian;
+ }
+ double v1, v2, s;
+ do {
+ v1 = (2 * this.nextDouble()) - 1; // between -1 and 1
+ v2 = (2 * this.nextDouble()) - 1; // between -1 and 1
+ s = (v1 * v1) + (v2 * v2);
+ } while ((s >= 1) || (s == 0));
+ final double multiplier = StrictMath.sqrt((-2 * StrictMath.log(s))/s);
+ this.nextNextGaussian = v2 * multiplier;
+ this.haveNextNextGaussian = true;
+ return v1 * multiplier;
+ }
+ /**
+ * Returns a pseudorandom, uniformly distributed {@code int} value between 0
+ * (inclusive) and the specified value (exclusive), drawn from this random
+ * number generator's sequence. The general contract of {@code nextInt} is
+ * that one {@code int} value in the specified range is pseudorandomly
+ * generated and returned. All {@code bound} possible {@code int} values are
+ * produced with (approximately) equal probability. The method
+ * {@code nextInt(int bound)} is implemented by class {@code Random} as if
+ * by:
+ * <pre> {@code
+ * public int nextInt(int bound) {
+ * if (bound <= 0)
+ * throw new IllegalArgumentException("bound must be positive");
+ *
+ * if ((bound & -bound) == bound) // i.e., bound is a power of 2
+ * return (int)((bound * (long)next(31)) >> 31);
+ *
+ * int bits, val;
+ * do {
+ * bits = next(31);
+ * val = bits % bound;
+ * } while (bits - val + (bound-1) < 0);
+ * return val;
+ * }}</pre>
+ *
+ * <p>The hedge "approx
+ * imately" is used in the foregoing description only because the next
+ * method is only approximately an unbiased source of independently chosen
+ * bits. If it were a perfect source of randomly chosen bits, then the
+ * algorithm shown would choose {@code int} values from the stated range
+ * with perfect uniformity.
+ * <p>
+ * The algorithm is slightly tricky. It rejects values that would result in
+ * an uneven distribution (due to the fact that 2^31 is not divisible by n).
+ * The probability of a value being rejected depends on n. The worst case is
+ * n=2^30+1, for which the probability of a reject is 1/2, and the expected
+ * number of iterations before the loop terminates is 2.
+ * <p>
+ * The algorithm treats the case where n is a power of two specially: it
+ * returns the correct number of high-order bits from the underlying
+ * pseudo-random number generator. In the absence of special treatment, the
+ * correct number of <i>low-order</i> bits would be returned. Linear
+ * congruential pseudo-random number generators such as the one implemented
+ * by this class are known to have short periods in the sequence of values
+ * of their low-order bits. Thus, this special case greatly increases the
+ * length of the sequence of values returned by successive calls to this
+ * method if n is a small power of two.
+ *
+ * @param bound the upper bound (exclusive). Must be positive.
+ * @return the next pseudorandom, uniformly distributed {@code int} value
+ * between zero (inclusive) and {@code bound} (exclusive) from this random
+ * number generator's sequence
+ * @throws IllegalArgumentException if bound is not positive
+ * @since 1.2
+ */
+ @Override
+ public int nextInt(final int bound) {
+ final int newBound;
+ if (bound <= 0) {
+ newBound = 1;
+ //throw new RuntimeException("BadBound");
+ }
+ else {
+ newBound = bound;
+ }
+
+ /*int r = next(31);
+ int m = bound - 1;
+ if ((bound & m) == 0) // i.e., bound is a power of 2
+ {
+ r = (int) ((bound * (long) r) >> 31);
+ } else {
+ for (int u = r;
+ u - (r = u % bound) + m < 0;
+ u = next(31))
+ ;
+ }
+ return r;*/
+ //speedup, new nextInt ~+40%
+ this.last = this.seed ^ (this.seed << 21);
+ this.last ^= (this.last >>> 35);
+ this.last ^= (this.last << 4);
+ this.seed = this.last;
+ final int out = (int) this.last % newBound;
+ return (out < 0) ? -out : out;
+ }
+ @Override
+ public int nextInt() {
+ return this.next(32);
+ }
+
+ @Override
+ public float nextFloat() {
+ return this.next(24) * FLOAT_UNIT;
+ }
+
+ @Override
+ public long nextLong() {
+ // it's okay that the bottom word remains signed.
+ return ((long)(this.next(32)) << 32) + this.next(32);
+ }
+
+ @Override
+ public void nextBytes(final byte[] bytes_arr) {
+ for (int iba = 0, lenba = bytes_arr.length; iba < lenba; ) {
+ for (int rndba = this.nextInt(),
+ nba = Math.min(lenba - iba, Integer.SIZE/Byte.SIZE);
+ nba-- > 0; rndba >>= Byte.SIZE) {
+ bytes_arr[iba++] = (byte)rndba;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/plugin/Sample_Plugin.java b/src/main/java/gtPlusPlus/api/plugin/Sample_Plugin.java
new file mode 100644
index 0000000000..543ec8e1fa
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/plugin/Sample_Plugin.java
@@ -0,0 +1,47 @@
+package gtPlusPlus.api.plugin;
+
+import gtPlusPlus.api.interfaces.IPlugin;
+import gtPlusPlus.plugin.manager.Core_Manager;
+
+public final class Sample_Plugin implements IPlugin {
+
+ public Sample_Plugin() {
+ Core_Manager.registerPlugin(this); //This must be called, else it won't load.
+ }
+
+ @Override
+ public boolean preInit() {
+ return true;
+ }
+
+ @Override
+ public boolean init() {
+ return true;
+ }
+
+ @Override
+ public boolean postInit() {
+ return true;
+ }
+
+ @Override
+ public boolean serverStart() {
+ return true;
+ }
+
+ @Override
+ public boolean serverStop() {
+ return true;
+ }
+
+ @Override
+ public String getPluginName() {
+ return "Sample Plugin";
+ }
+
+ @Override
+ public String getPluginAbbreviation() {
+ return "Test";
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/api/thermal/energy/IThermalConnection.java b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalConnection.java
new file mode 100644
index 0000000000..d8573000fc
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalConnection.java
@@ -0,0 +1,7 @@
+package gtPlusPlus.api.thermal.energy;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+public interface IThermalConnection {
+ boolean canConnectThermalEnergy(ForgeDirection arg0);
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/energy/IThermalContainerItem.java b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalContainerItem.java
new file mode 100644
index 0000000000..072695bd76
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalContainerItem.java
@@ -0,0 +1,15 @@
+package gtPlusPlus.api.thermal.energy;
+
+import net.minecraft.item.ItemStack;
+
+public interface IThermalContainerItem {
+
+ int receiveThermalEnergy(ItemStack arg0, int arg1, boolean arg2);
+
+ int extractThermalEnergy(ItemStack arg0, int arg1, boolean arg2);
+
+ int getThermalEnergyStored(ItemStack arg0);
+
+ int getMaxThermalEnergyStored(ItemStack arg0);
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/energy/IThermalHandler.java b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalHandler.java
new file mode 100644
index 0000000000..3ab7127757
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalHandler.java
@@ -0,0 +1,15 @@
+package gtPlusPlus.api.thermal.energy;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+public interface IThermalHandler extends IThermalProvider, IThermalReceiver {
+
+ int receiveThermalEnergy(ForgeDirection arg0, int arg1, boolean arg2);
+
+ int extractThermalEnergy(ForgeDirection arg0, int arg1, boolean arg2);
+
+ int getThermalEnergyStored(ForgeDirection arg0);
+
+ int getMaxThermalEnergyStored(ForgeDirection arg0);
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/energy/IThermalProvider.java b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalProvider.java
new file mode 100644
index 0000000000..0e4a060b23
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalProvider.java
@@ -0,0 +1,13 @@
+package gtPlusPlus.api.thermal.energy;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+public interface IThermalProvider extends IThermalConnection {
+
+ int extractThermalEnergy(ForgeDirection arg0, int arg1, boolean arg2);
+
+ int getThermalEnergyStored(ForgeDirection arg0);
+
+ int getMaxThermalEnergyStored(ForgeDirection arg0);
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/energy/IThermalReceiver.java b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalReceiver.java
new file mode 100644
index 0000000000..e08ce48a06
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalReceiver.java
@@ -0,0 +1,13 @@
+package gtPlusPlus.api.thermal.energy;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+public interface IThermalReceiver extends IThermalConnection {
+
+ int receiveThermalEnergy(ForgeDirection arg0, int arg1, boolean arg2);
+
+ int getThermalEnergyStored(ForgeDirection arg0);
+
+ int getMaxThermalEnergyStored(ForgeDirection arg0);
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/energy/IThermalStorage.java b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalStorage.java
new file mode 100644
index 0000000000..db3e6c8966
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/energy/IThermalStorage.java
@@ -0,0 +1,13 @@
+package gtPlusPlus.api.thermal.energy;
+
+public interface IThermalStorage {
+
+ int receiveThermalEnergy(int arg0, boolean arg1);
+
+ int extractThermalEnergy(int arg0, boolean arg1);
+
+ int getThermalEnergyStored();
+
+ int getMaxThermalEnergyStored();
+
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/energy/ThermalStorage.java b/src/main/java/gtPlusPlus/api/thermal/energy/ThermalStorage.java
new file mode 100644
index 0000000000..9c7bb0066c
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/energy/ThermalStorage.java
@@ -0,0 +1,116 @@
+package gtPlusPlus.api.thermal.energy;
+
+import net.minecraft.nbt.NBTTagCompound;
+
+public class ThermalStorage implements IThermalStorage {
+
+ protected int thermal_energy;
+ protected int capacity;
+ protected int maxReceive;
+ protected int maxExtract;
+
+ public ThermalStorage(int arg0) {
+ this(arg0, arg0, arg0);
+ }
+
+ public ThermalStorage(int arg0, int arg1) {
+ this(arg0, arg1, arg1);
+ }
+
+ public ThermalStorage(int arg0, int arg1, int arg2) {
+ this.capacity = arg0;
+ this.maxReceive = arg1;
+ this.maxExtract = arg2;
+ }
+
+ public ThermalStorage readFromNBT(NBTTagCompound arg0) {
+ this.thermal_energy = arg0.getInteger("ThermalEnergy");
+ if (this.thermal_energy > this.capacity) {
+ this.thermal_energy = this.capacity;
+ }
+ return this;
+ }
+
+ public NBTTagCompound writeToNBT(NBTTagCompound arg0) {
+ if (this.thermal_energy < 0) {
+ this.thermal_energy = 0;
+ }
+ arg0.setInteger("ThermalEnergy", this.thermal_energy);
+ return arg0;
+ }
+
+ public void setCapacity(int arg0) {
+ this.capacity = arg0;
+ if (this.thermal_energy > arg0) {
+ this.thermal_energy = arg0;
+ }
+
+ }
+
+ public void setMaxTransfer(int arg0) {
+ this.setMaxReceive(arg0);
+ this.setMaxExtract(arg0);
+ }
+
+ public void setMaxReceive(int arg0) {
+ this.maxReceive = arg0;
+ }
+
+ public void setMaxExtract(int arg0) {
+ this.maxExtract = arg0;
+ }
+
+ public int getMaxReceive() {
+ return this.maxReceive;
+ }
+
+ public int getMaxExtract() {
+ return this.maxExtract;
+ }
+
+ public void setEnergyStored(int arg0) {
+ this.thermal_energy = arg0;
+ if (this.thermal_energy > this.capacity) {
+ this.thermal_energy = this.capacity;
+ } else if (this.thermal_energy < 0) {
+ this.thermal_energy = 0;
+ }
+
+ }
+
+ public void modifyEnergyStored(int arg0) {
+ this.thermal_energy += arg0;
+ if (this.thermal_energy > this.capacity) {
+ this.thermal_energy = this.capacity;
+ } else if (this.thermal_energy < 0) {
+ this.thermal_energy = 0;
+ }
+
+ }
+
+ public int receiveThermalEnergy(int arg0, boolean arg1) {
+ int arg2 = Math.min(this.capacity - this.thermal_energy, Math.min(this.maxReceive, arg0));
+ if (!arg1) {
+ this.thermal_energy += arg2;
+ }
+
+ return arg2;
+ }
+
+ public int extractThermalEnergy(int arg0, boolean arg1) {
+ int arg2 = Math.min(this.thermal_energy, Math.min(this.maxExtract, arg0));
+ if (!arg1) {
+ this.thermal_energy -= arg2;
+ }
+
+ return arg2;
+ }
+
+ public int getThermalEnergyStored() {
+ return this.thermal_energy;
+ }
+
+ public int getMaxThermalEnergyStored() {
+ return this.capacity;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/energy/ThermalStorageAdv.java b/src/main/java/gtPlusPlus/api/thermal/energy/ThermalStorageAdv.java
new file mode 100644
index 0000000000..47af7e79a6
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/energy/ThermalStorageAdv.java
@@ -0,0 +1,34 @@
+package gtPlusPlus.api.thermal.energy;
+
+public class ThermalStorageAdv extends ThermalStorage {
+
+ public ThermalStorageAdv(int arg0) {
+ this(arg0, arg0, arg0);
+ }
+
+ public ThermalStorageAdv(int arg0, int arg1) {
+ this(arg0, arg1, arg1);
+ }
+
+ public ThermalStorageAdv(int arg0, int arg1, int arg2) {
+ super(arg0, arg1, arg2);
+ }
+
+ public int receiveEnergyNoLimit(int arg0, boolean arg1) {
+ int arg2 = Math.min(super.capacity - super.thermal_energy, arg0);
+ if (!arg1) {
+ super.thermal_energy += arg2;
+ }
+
+ return arg2;
+ }
+
+ public int extractEnergyNoLimit(int arg0, boolean arg1) {
+ int arg2 = Math.min(super.thermal_energy, arg0);
+ if (!arg1) {
+ super.thermal_energy -= arg2;
+ }
+
+ return arg2;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/sample/ItemThermalContainer.java b/src/main/java/gtPlusPlus/api/thermal/sample/ItemThermalContainer.java
new file mode 100644
index 0000000000..015e5fd5f3
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/sample/ItemThermalContainer.java
@@ -0,0 +1,84 @@
+package gtPlusPlus.api.thermal.sample;
+
+import gtPlusPlus.api.thermal.energy.IThermalContainerItem;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+public class ItemThermalContainer extends Item implements IThermalContainerItem {
+ protected int capacity;
+ protected int maxReceive;
+ protected int maxExtract;
+
+ public ItemThermalContainer() {
+ }
+
+ public ItemThermalContainer(int arg0) {
+ this(arg0, arg0, arg0);
+ }
+
+ public ItemThermalContainer(int arg0, int arg1) {
+ this(arg0, arg1, arg1);
+ }
+
+ public ItemThermalContainer(int arg0, int arg1, int arg2) {
+ this.capacity = arg0;
+ this.maxReceive = arg1;
+ this.maxExtract = arg2;
+ }
+
+ public ItemThermalContainer setCapacity(int arg0) {
+ this.capacity = arg0;
+ return this;
+ }
+
+ public void setMaxTransfer(int arg0) {
+ this.setMaxReceive(arg0);
+ this.setMaxExtract(arg0);
+ }
+
+ public void setMaxReceive(int arg0) {
+ this.maxReceive = arg0;
+ }
+
+ public void setMaxExtract(int arg0) {
+ this.maxExtract = arg0;
+ }
+
+ public int receiveThermalEnergy(ItemStack arg0, int arg1, boolean arg2) {
+ if (arg0.getTagCompound() == null) {
+ arg0.stackTagCompound = new NBTTagCompound();
+ }
+ int arg3 = arg0.stackTagCompound.getInteger("ThermalEnergy");
+ int arg4 = Math.min(this.capacity - arg3, Math.min(this.maxReceive, arg1));
+ if (!arg2) {
+ arg3 += arg4;
+ arg0.stackTagCompound.setInteger("ThermalEnergy", arg3);
+ }
+ return arg4;
+ }
+
+ public int extractThermalEnergy(ItemStack arg0, int arg1, boolean arg2) {
+ if (arg0.stackTagCompound != null && arg0.stackTagCompound.hasKey("ThermalEnergy")) {
+ int arg3 = arg0.stackTagCompound.getInteger("ThermalEnergy");
+ int arg4 = Math.min(arg3, Math.min(this.maxExtract, arg1));
+ if (!arg2) {
+ arg3 -= arg4;
+ arg0.stackTagCompound.setInteger("ThermalEnergy", arg3);
+ }
+ return arg4;
+ } else {
+ return 0;
+ }
+ }
+
+ public int getThermalEnergyStored(ItemStack arg0) {
+ return arg0.stackTagCompound != null && arg0.stackTagCompound.hasKey("ThermalEnergy")
+ ? arg0.stackTagCompound.getInteger("ThermalEnergy")
+ : 0;
+ }
+
+ public int getMaxThermalEnergyStored(ItemStack arg0) {
+ return this.capacity;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/sample/TileThermalHandler.java b/src/main/java/gtPlusPlus/api/thermal/sample/TileThermalHandler.java
new file mode 100644
index 0000000000..e2e3c50ab7
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/sample/TileThermalHandler.java
@@ -0,0 +1,42 @@
+package gtPlusPlus.api.thermal.sample;
+
+import gtPlusPlus.api.thermal.energy.IThermalHandler;
+import gtPlusPlus.api.thermal.energy.ThermalStorage;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+
+public class TileThermalHandler extends TileEntity implements IThermalHandler {
+
+ protected ThermalStorage storage = new ThermalStorage(32000);
+
+ public void readFromNBT(NBTTagCompound arg0) {
+ super.readFromNBT(arg0);
+ this.storage.readFromNBT(arg0);
+ }
+
+ public void writeToNBT(NBTTagCompound arg0) {
+ super.writeToNBT(arg0);
+ this.storage.writeToNBT(arg0);
+ }
+
+ public boolean canConnectThermalEnergy(ForgeDirection arg0) {
+ return true;
+ }
+
+ public int receiveThermalEnergy(ForgeDirection arg0, int arg1, boolean arg2) {
+ return this.storage.receiveThermalEnergy(arg1, arg2);
+ }
+
+ public int extractThermalEnergy(ForgeDirection arg0, int arg1, boolean arg2) {
+ return this.storage.extractThermalEnergy(arg1, arg2);
+ }
+
+ public int getThermalEnergyStored(ForgeDirection arg0) {
+ return this.storage.getThermalEnergyStored();
+ }
+
+ public int getMaxThermalEnergyStored(ForgeDirection arg0) {
+ return this.storage.getMaxThermalEnergyStored();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/api/thermal/tileentity/IThermalInfo.java b/src/main/java/gtPlusPlus/api/thermal/tileentity/IThermalInfo.java
new file mode 100644
index 0000000000..a40535887c
--- /dev/null
+++ b/src/main/java/gtPlusPlus/api/thermal/tileentity/IThermalInfo.java
@@ -0,0 +1,13 @@
+package gtPlusPlus.api.thermal.tileentity;
+
+public interface IThermalInfo {
+
+ int getInfoEnergyPerTick();
+
+ int getInfoMaxEnergyPerTick();
+
+ int getInfoEnergyStored();
+
+ int getInfoMaxEnergyStored();
+
+} \ No newline at end of file