aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common/tileentities
diff options
context:
space:
mode:
authorLéa Gris <lea.gris@noiraude.net>2018-10-07 18:17:17 +0200
committerDream-Master <dream-master@gmx.net>2018-10-07 20:58:55 +0200
commit4f5513db807ec0e14dd1331aeefe38e8e4ac6ab4 (patch)
treed99440fbe1b23b08f0a58b25eec2aac3ce9f141f /src/main/java/gregtech/common/tileentities
parent364d417a3eea8d79f7c5102dd13aabaaa809b525 (diff)
downloadGT5-Unofficial-4f5513db807ec0e14dd1331aeefe38e8e4ac6ab4.tar.gz
GT5-Unofficial-4f5513db807ec0e14dd1331aeefe38e8e4ac6ab4.tar.bz2
GT5-Unofficial-4f5513db807ec0e14dd1331aeefe38e8e4ac6ab4.zip
cherry pick 3531fb264fe46af2168340d4a38528dc116a2ce3 [3531fb2]
Magical Energy Absorber fix stop drain and rework Vis to EU Conversion ( #1478) * fix(magicalenergyabsorber) stops when buffer can not store the next maximum eu output * rework(magicalenergyabsorber): computation of vis to eu conversion New configuration option to define how much EU Per Vis (not CVis) I:EnergyPerVis_20=20 This value is divided by 100, so it is actually 0.2 EU per Vis The Magical Energy Absorber will try to drain enough CVis, comulating all aspects, until it can reach max Output, or has drained all available aspects. Number of total cummulated CVis output required in a Node per Magical Energy Absorber Tier: Novice (LV): √(32 × 10000 ÷ (20 × 90)) = 13,333333333 ⇒ 13 CVis Adept (MV); √(128 × 10000 ÷ (20 × 80)) = 28,2843 ⇒ 28 CVis Master (HV): √(512 × 10000 ÷ (20 × 70)) = 60,474315681 ⇒ 60 CVis Grand Master (EV): √(2048 × 10000 ÷ (20 × 60)) = 130,639452948 ⇒ 131 CVis As referrence: The Huge Creative Node from Thaumcraft has 500 of each primal aspects. * fix(machine): magic energy absorber - Fixed Dragon Egg Siphon mode to work as intended when `B:MagicEnergyAbsorber.AllowMultipleEggs_false=false` (fix #1482) - Fixed Vis drain from Visnet (Energized Node/Vis Relay) drain rate (fix #1119) - Added Vis conversion as a configuration option: `I:MagicEnergyAbsorber.EnergyPerVis_20=20` - Replaced broken Aspect drain from items, with drain from Essentia Containers in range, using same mechanic as the Infusion Altar - Added Essentia Aspect conversion as a configuration option: `I:MagicEnergyAbsorber.EnergyPerEssentia_320=320` - Fixed Enchantments drain to convert all available enchantments - Made input filtered to valid enchanted items/books (Item must be enchantable and enchanted) - Fixed Enchantments drain to not consume input; if it can not buffer generated energy from it, or if it can not output disenchanted item - Added a user settable Tiered operation range using a Screwdriver. Default Range Tier is Machine Tier. Max Range Tier is Machine Tier + 2. Range is 2^(Range Tier): 1, 2, 4, 8, 16, 32, 64 blocks - Fixed Ender Crystal drain mechanic, to allow multiple Crystals to be drained. - Made each in-use Ender Crystal, exclusive to a Magic Energy Absorber - Improved default Ender Crystal energy worth to 512EU/t instead of 32EU/t
Diffstat (limited to 'src/main/java/gregtech/common/tileentities')
-rw-r--r--src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicalEnergyAbsorber.java735
1 files changed, 539 insertions, 196 deletions
diff --git a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicalEnergyAbsorber.java b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicalEnergyAbsorber.java
index 3bc2731d4a..bb3b24f5e3 100644
--- a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicalEnergyAbsorber.java
+++ b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicalEnergyAbsorber.java
@@ -1,8 +1,8 @@
package gregtech.common.tileentities.generators;
+import com.google.common.base.Enums;
import cpw.mods.fml.common.Loader;
import gregtech.api.GregTech_API;
-import gregtech.api.enums.ConfigCategories;
import gregtech.api.enums.TC_Aspects;
import gregtech.api.enums.Textures;
import gregtech.api.interfaces.ITexture;
@@ -10,285 +10,628 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicGenerator;
import gregtech.api.objects.GT_RenderedTexture;
-import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.*;
import net.minecraft.block.Block;
+import net.minecraft.block.BlockDragonEgg;
import net.minecraft.enchantment.Enchantment;
+import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.item.EntityEnderCrystal;
+import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemEnchantedBook;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
+import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.common.util.ForgeDirection;
import thaumcraft.api.aspects.Aspect;
-import thaumcraft.api.aspects.AspectList;
-import thaumcraft.api.aspects.IEssentiaContainerItem;
+import thaumcraft.api.aspects.AspectSourceHelper;
+import thaumcraft.api.aspects.IAspectSource;
import thaumcraft.api.visnet.VisNetHandler;
-import java.util.ArrayList;
-import java.util.Locale;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import static gregtech.api.enums.ConfigCategories.machineconfig;
+import static gregtech.api.enums.GT_Values.MOD_ID_TC;
import static gregtech.api.enums.GT_Values.V;
-
-public class GT_MetaTileEntity_MagicalEnergyAbsorber extends GT_MetaTileEntity_BasicGenerator {
-
- public static final ArrayList<EntityEnderCrystal> sUsedDragonCrystalList = new ArrayList<EntityEnderCrystal>();
- public static boolean sAllowMultipleEggs = true;
- public static GT_MetaTileEntity_MagicalEnergyAbsorber mActiveSiphon = null;
- public static int sEnergyPerEnderCrystal = 32;
- public static int sEnergyFromVis = 512;
- public static int sDragonEggEnergyPerTick = 128;
- public static boolean isThaumcraftLoaded;
- public int mEfficiency;
- public EntityEnderCrystal mTargetedCrystal;
+import static net.minecraft.util.EnumChatFormatting.*;
+
+interface MagicalEnergyBBListener {
+ void onMagicalEnergyBBUpdate();
+}
+
+public class GT_MetaTileEntity_MagicalEnergyAbsorber extends GT_MetaTileEntity_BasicGenerator implements MagicalEnergyBBListener {
+
+ private static final boolean THAUMCRAFT_LOADED = Loader.isModLoaded(MOD_ID_TC);
+ private static final ConcurrentHashMap<UUID, GT_MetaTileEntity_MagicalEnergyAbsorber> sSubscribedCrystals = new ConcurrentHashMap<>(4);
+ private static List<Aspect> sPrimalAspects = (THAUMCRAFT_LOADED) ? Aspect.getPrimalAspects() : new ArrayList<Aspect>();
+ private static boolean sAllowMultipleEggs = false;
+ private static GT_MetaTileEntity_MagicalEnergyAbsorber sActiveSiphon = null;
+ private static int sEnergyPerEndercrystal = 512;
+ private static int sEnergyFromVis = 20;
+ private static int sEnergyPerEssentia = 320;
+ private static Map<Aspect, Integer> sAspectsEnergy = new HashMap<>();
+ private static int sDragonEggEnergyPerTick = 2048;
+ private int mEfficiency;
+ private int mMaxVisPerDrain;
+ private MagicalEnergyBB mMagicalEnergyBB = new MagicalEnergyBB(this, mTier, mTier + 2);
+ private long mNextGenerateTickRate = 1;
+ private int mNoGenerationTicks = 0;
public GT_MetaTileEntity_MagicalEnergyAbsorber(int aID, String aName, String aNameRegional, int aTier) {
- super(aID, aName, aNameRegional, aTier, "Feasts on magic close to it", new ITexture[0]);
- onConfigLoad();
+ super(aID, aName, aNameRegional, aTier, "Feasts on magic close to it:");
+ onConfigLoad(GregTech_API.sMachineFile);
}
- public GT_MetaTileEntity_MagicalEnergyAbsorber(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ private GT_MetaTileEntity_MagicalEnergyAbsorber(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
super(aName, aTier, aDescription, aTextures);
- onConfigLoad();
+ onConfigLoad(GregTech_API.sMachineFile);
}
- public GT_MetaTileEntity_MagicalEnergyAbsorber(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
- super(aName, aTier, aDescription, aTextures);
- onConfigLoad();
- }
-
- public boolean isOutputFacing(byte aSide) {
- return aSide == getBaseMetaTileEntity().getFrontFacing();
+ /**
+ * Populates static variables dependant on config settings
+ *
+ * @param aConfig GT_Config
+ */
+ private static void sharedConfigLoad(GT_Config aConfig) {
+ sAllowMultipleEggs = aConfig.get(machineconfig, "MagicEnergyAbsorber.AllowMultipleEggs", false);
+ sDragonEggEnergyPerTick = aConfig.get(machineconfig, "MagicEnergyAbsorber.EnergyPerTick.DragonEgg", 2048);
+ sEnergyPerEndercrystal = aConfig.get(machineconfig, "MagicEnergyAbsorber.EnergyPerTick.EnderCrystal", 512);
+ if (THAUMCRAFT_LOADED) {
+ sEnergyFromVis = aConfig.get(machineconfig, "MagicEnergyAbsorber.EnergyPerVis", 20);
+ sEnergyPerEssentia = aConfig.get(machineconfig, "MagicEnergyAbsorber.EnergyPerEssentia", 320);
+ for (Aspect tAspect : Aspect.aspects.values()) {
+ sAspectsEnergy.put(tAspect,
+ Enums.getIfPresent(TC_Aspects.class,
+ tAspect.getTag().toUpperCase(Locale.ENGLISH)).or(TC_Aspects.AER).mValue
+ * sEnergyPerEssentia);
+ }
+ }
}
- public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
- return new GT_MetaTileEntity_MagicalEnergyAbsorber(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ private static void setActiveSiphon(GT_MetaTileEntity_MagicalEnergyAbsorber aSiphon) {
+ sActiveSiphon = aSiphon;
}
- public GT_Recipe.GT_Recipe_Map getRecipes() {
- return GT_Recipe.GT_Recipe_Map.sMagicFuels;
+ @Override
+ public void onConfigLoad(GT_Config aConfig) {
+ sharedConfigLoad(aConfig);
+ mEfficiency = aConfig.get(machineconfig, "MagicEnergyAbsorber.efficiency.tier." + mTier, 100 - mTier * 10);
+ mMaxVisPerDrain = (int) Math.round(Math.sqrt(V[mTier] * 10000 / (sEnergyFromVis * (getEfficiency() != 0 ? getEfficiency() : 100))));
+ if (Math.pow(mMaxVisPerDrain, 2) * sEnergyFromVis * (getEfficiency() != 0 ? getEfficiency() : 100) < V[mTier]) {
+ mMaxVisPerDrain += 1;
+ }
}
- public int getCapacity() {
- return 16000;
+ @Override
+ public void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) mMagicalEnergyBB.decreaseTier();
+ else mMagicalEnergyBB.increaseTier();
+ GT_Utility.sendChatToPlayer(aPlayer, String.format(GT_LanguageManager.addStringLocalization("Interaction_DESCRIPTION_MagicalEnergyAbsorber_Screwdriver", "Absorption range: %s blocks"), mMagicalEnergyBB.getRange(), true));
+ mMagicalEnergyBB.update();
}
- public void onConfigLoad() {
- this.mEfficiency = GregTech_API.sMachineFile.get(ConfigCategories.machineconfig, "MagicEnergyAbsorber.efficiency.tier." + this.mTier,
- 100 - this.mTier * 10);
- this.sAllowMultipleEggs = GregTech_API.sMachineFile.get(ConfigCategories.machineconfig, "MagicEnergyAbsorber.AllowMultipleEggs", false);
- this.sEnergyPerEnderCrystal = GregTech_API.sMachineFile.get(ConfigCategories.machineconfig, "MagicEnergyAbsorber.EnergyPerTick.EnderCrystal", 32);
- this.sEnergyFromVis = (GregTech_API.sMachineFile.get(ConfigCategories.machineconfig, "MagicEnergyAbsorber.EnergyPerVisDivisor", 2500) * 10);
- this.sDragonEggEnergyPerTick = GregTech_API.sMachineFile.get(ConfigCategories.machineconfig, "MagicEnergyAbsorber.EnergyPerTick", 2048);
- this.isThaumcraftLoaded = Loader.isModLoaded("Thaumcraft");
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (!aBaseMetaTileEntity.isServerSide()) return;
+ mMagicalEnergyBB.update();
}
@Override
- public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
- if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.isAllowedToWork()
- && aBaseMetaTileEntity.getUniversalEnergyStored() < maxEUOutput() + aBaseMetaTileEntity.getEUCapacity()) {
- // Dragon Egg
- if (hasEgg() && aTick % 10 == 0) {
- getBaseMetaTileEntity().increaseStoredEnergyUnits(sDragonEggEnergyPerTick * getEfficiency() / 10, false);
- if ((mActiveSiphon != this) && (!sAllowMultipleEggs)) {
- if ((mActiveSiphon == null) || (mActiveSiphon.getBaseMetaTileEntity() == null)
- || (mActiveSiphon.getBaseMetaTileEntity().isInvalidTileEntity()) || (!mActiveSiphon.hasEgg())) {
- mActiveSiphon = this;
- } else {
- Block tEgg = mActiveSiphon.getBaseMetaTileEntity().getBlockOffset(0, 1, 0);
- if (!getBaseMetaTileEntity().getWorld().getChunkFromBlockCoords(mActiveSiphon.getBaseMetaTileEntity().getXCoord(), mActiveSiphon.getBaseMetaTileEntity().getZCoord()).isChunkLoaded && (tEgg == Blocks.dragon_egg || tEgg.getUnlocalizedName().equals("tile.dragonEgg"))) {
- getBaseMetaTileEntity().doExplosion(Integer.MAX_VALUE);
- } else {
- mActiveSiphon = this;
- }
- }
- }
- }
- // Energyzed node
- if (isThaumcraftLoaded) {
- try {
- int multFactor = 2;
- World tmpWorld = this.getBaseMetaTileEntity().getWorld();
- int tmpX = this.getBaseMetaTileEntity().getXCoord();
- int tmpY = this.getBaseMetaTileEntity().getYCoord();
- int tmpZ = this.getBaseMetaTileEntity().getZCoord();
- int fire = VisNetHandler.drainVis(tmpWorld, tmpX, tmpY, tmpZ, Aspect.FIRE, 1000); // all of these should be 1000
- int earth = VisNetHandler.drainVis(tmpWorld, tmpX, tmpY, tmpZ, Aspect.EARTH, 1000);
- int air = VisNetHandler.drainVis(tmpWorld, tmpX, tmpY, tmpZ, Aspect.AIR, 1000);
- int entropy = VisNetHandler.drainVis(tmpWorld, tmpX, tmpY, tmpZ, Aspect.ENTROPY, 1000);
- int order = VisNetHandler.drainVis(tmpWorld, tmpX, tmpY, tmpZ, Aspect.ORDER, 1000);
- int water = VisNetHandler.drainVis(tmpWorld, tmpX, tmpY, tmpZ, Aspect.WATER, 1000);
- int visEU = (int) (Math.pow(fire, 2) + Math.pow(earth, 2) + Math.pow(air, 2) + Math.pow(entropy, 2) + Math.pow(order, 2) + Math.pow(water, 2));
- int mult = 0; //this should make it more dependant on how big your node is
- mult += fire * multFactor;
- mult += earth * multFactor;
- mult += air * multFactor;
- mult += entropy * multFactor;
- mult += order * multFactor;
- mult += water * multFactor;
- visEU = (visEU * mult) / 100;
-
- getBaseMetaTileEntity().increaseStoredEnergyUnits(Math.min(maxEUOutput(), visEU * getEfficiency() / sEnergyFromVis), false);
-
- } catch (Throwable e) {
-
- }
- }
- // EnderCrystal
- if (sEnergyPerEnderCrystal > 0) {
- if (this.mTargetedCrystal == null) {
- ArrayList<EntityEnderCrystal> tList = (ArrayList) getBaseMetaTileEntity().getWorld().getEntitiesWithinAABB(
- EntityEnderCrystal.class,
- AxisAlignedBB.getBoundingBox(getBaseMetaTileEntity().getXCoord() - 64, getBaseMetaTileEntity().getYCoord() - 64,
- getBaseMetaTileEntity().getZCoord() - 64, getBaseMetaTileEntity().getXCoord() + 64,
- getBaseMetaTileEntity().getYCoord() + 64, getBaseMetaTileEntity().getZCoord() + 64));
- if ((tList != null) && (!tList.isEmpty())) {
- tList.removeAll(sUsedDragonCrystalList);
- if (tList.size() > 0) {
- this.mTargetedCrystal = ((EntityEnderCrystal) tList.get(0));
- if (this.mTargetedCrystal != null) {
- sUsedDragonCrystalList.add(this.mTargetedCrystal);
- }
- }
- }
- } else if (this.mTargetedCrystal.isEntityAlive()) {
- getBaseMetaTileEntity().increaseStoredEnergyUnits(sEnergyPerEnderCrystal * 10, false);
- } else {
- sUsedDragonCrystalList.remove(this.mTargetedCrystal);
- this.mTargetedCrystal = null;
- }
- }
-
- // Absorb entchantments and TC essentia
- try {
- if ((this.mInventory[0] != null) && (this.mInventory[1] == null)) {
- if (isThaumcraftLoaded && this.mInventory[0].getItem() instanceof IEssentiaContainerItem) {
- AspectList tAspect = ((IEssentiaContainerItem) this.mInventory[0].getItem()).getAspects(this.mInventory[0]);
- TC_Aspects tValue = TC_Aspects.valueOf(tAspect.getAspects()[0].getTag().toUpperCase(Locale.ENGLISH));
- int tEU = (tValue.mValue * tAspect.getAmount((Aspect) tValue.mAspect) * 100);
- getBaseMetaTileEntity().increaseStoredEnergyUnits(tEU * getEfficiency() / 100, true);
- ItemStack tStack = this.mInventory[0].copy();
- tStack.setTagCompound(null);
- tStack.setItemDamage(0);
- tStack.stackSize = 1;
- this.mInventory[1] = tStack;
- this.mInventory[0].stackSize--;
- if (this.mInventory[0].stackSize < 1) {
- this.mInventory[0] = null;
- }
-
- } else {
- if ((this.mInventory[0].isItemEnchanted()) && (this.mInventory[0].getItem().getItemEnchantability() > 0)) {
- NBTTagList tEnchantments = this.mInventory[0].getEnchantmentTagList();
- if (tEnchantments != null) {
- for (int i = 0; i < tEnchantments.tagCount(); i++) {
- short tID = ((NBTTagCompound) tEnchantments.getCompoundTagAt(i)).getShort("id");
- short tLevel = ((NBTTagCompound) tEnchantments.getCompoundTagAt(i)).getShort("lvl");
- if ((tID > -1) && (tID < Enchantment.enchantmentsList.length)) {
- Enchantment tEnchantment = Enchantment.enchantmentsList[tID];
- if (tEnchantment != null) {
- getBaseMetaTileEntity().increaseStoredEnergyUnits(
- 1000000 * getEfficiency() * tLevel / (tEnchantment.getMaxLevel() * tEnchantment.getWeight() * 100), true);
- }
- }
- }
- this.mInventory[0].stackTagCompound.removeTag("ench");
- }
- } else if ((this.mInventory[0].getItem() instanceof ItemEnchantedBook)) {
- NBTTagList tEnchantments = ((ItemEnchantedBook) this.mInventory[0].getItem()).func_92110_g(this.mInventory[0]);
- if (tEnchantments != null) {
- for (int i = 0; i < tEnchantments.tagCount(); i++) {
- short tID = ((NBTTagCompound) tEnchantments.getCompoundTagAt(i)).getShort("id");
- short tLevel = ((NBTTagCompound) tEnchantments.getCompoundTagAt(i)).getShort("lvl");
- if ((tID > -1) && (tID < Enchantment.enchantmentsList.length)) {
- Enchantment tEnchantment = Enchantment.enchantmentsList[tID];
- if (tEnchantment != null) {
- getBaseMetaTileEntity().increaseStoredEnergyUnits(
- 1000000 * tLevel / (tEnchantment.getMaxLevel() * tEnchantment.getWeight()), true);
- }
- }
- }
- this.mInventory[0] = new ItemStack(Items.book, 1);
- }
- }
- this.mInventory[1] = this.mInventory[0];
- this.mInventory[0] = null;
- }
- }
- } catch (Throwable e) {
- }
- }
+ public void onRemoval() {
+ super.onRemoval();
+ releaseEgg();
+ unsubscribeCrystals();
}
- public void inValidate() {
- if (mActiveSiphon == this) {
- mActiveSiphon = null;
+ private void releaseEgg() {
+ if (sActiveSiphon == this) {
+ setActiveSiphon(null);
}
}
- public boolean hasEgg() {
- Block above = getBaseMetaTileEntity().getBlockOffset(0, 1, 0);
- if (above == null || Blocks.air == above) {
- return false;
+ private void unsubscribeCrystals() {
+ for (UUID tCrystalID : sSubscribedCrystals.keySet()) {
+ sSubscribedCrystals.remove(tCrystalID, this);
}
- return Blocks.dragon_egg == above || above.getUnlocalizedName().equals("tile.dragonEgg");
}
- public int getEfficiency() {
- return this.mEfficiency;
+ /**
+ * Call-back from the Bounding Box when its content is updated
+ */
+ @Override
+ public void onMagicalEnergyBBUpdate() {
+ List<UUID> tCrystalIDsInRange = mMagicalEnergyBB.getLivingCrystalIDs();
+ // Release unreachable Crystals subscriptions
+ for (UUID tSubscribedCrystalID : sSubscribedCrystals.keySet()) {
+ if (!tCrystalIDsInRange.contains(tSubscribedCrystalID)) {
+ sSubscribedCrystals.remove(tSubscribedCrystalID, this);
+ }
+ }
+ // Subscribe to available and not already subscribed Crystals
+ for (UUID tCrystalID : tCrystalIDsInRange) {
+ sSubscribedCrystals.putIfAbsent(tCrystalID, this);
+ }
}
@Override
- public long maxEUStore() {
- return Math.max(getEUVar(), V[mTier] * 16000L + getMinimumStoredEU());
+ public String[] getDescription() {
+ final String LI = "-%%%";
+ final String EU_PER = "%%%EU per ";
+ List<String> description = new ArrayList<>();
+ description.add(UNDERLINE + "Feasts on " + LIGHT_PURPLE + UNDERLINE + "magic" + GRAY + UNDERLINE + " close to it:");
+ description.add(LI + (sAllowMultipleEggs ? "A " : "An " + YELLOW + UNDERLINE + "EXCLUSIVE" + RESET) + GRAY + " " + LIGHT_PURPLE + "Dragon Egg" + GRAY + " atop");
+ if (sEnergyPerEndercrystal > 0) {
+ description.add(LI + sEnergyPerEndercrystal + EU_PER + LIGHT_PURPLE + "Ender Crystal" + GRAY + " in range");
+ }
+ if (THAUMCRAFT_LOADED) {
+ description.add(LI + mMaxVisPerDrain + "%%%CV/t from an " + LIGHT_PURPLE + "Energised Node" + GRAY);
+ description.add(LI + (sEnergyPerEssentia * getEfficiency()) / 100 + EU_PER + LIGHT_PURPLE + "Essentia" + GRAY + " Aspect-Value from containers in range");
+ }
+ description.add(" ");
+ description.add(UNDERLINE + "Lookup range (Use Screwdriver to change):");
+ description.add("Default:%%%" + GREEN + mMagicalEnergyBB.getDefaultRange());
+ description.add("Max:%%%" + GREEN + mMagicalEnergyBB.getMaxRange());
+ description.add(" ");
+ description.add(UNDERLINE + "Fuels on " + LIGHT_PURPLE + UNDERLINE + "enchantments" + GRAY + UNDERLINE + " input:");
+ description.add("- Item:%%%" + (10000 * getEfficiency()) / 100 + EU_PER + LIGHT_PURPLE + "enchant" + GRAY + " weight × level / max");
+ description.add("- Book:%%%" + 10000 + EU_PER + LIGHT_PURPLE + "enchant" + GRAY + " weight × level / max");
+ description.add(" ");
+ description.add("Efficiency:%%%" + GREEN + getEfficiency() + "%");
+ return description.toArray(new String[0]);
}
+ @Override
public ITexture[] getFront(byte aColor) {
return new ITexture[]{super.getFront(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_MAGIC),
- Textures.BlockIcons.OVERLAYS_ENERGY_OUT[this.mTier]};
+ Textures.BlockIcons.OVERLAYS_ENERGY_OUT[mTier]};
}
+ @Override
public ITexture[] getBack(byte aColor) {
return new ITexture[]{super.getBack(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT)};
}
+ @Override
public ITexture[] getBottom(byte aColor) {
return new ITexture[]{super.getBottom(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_MAGIC)};
}
+ @Override
public ITexture[] getTop(byte aColor) {
return new ITexture[]{super.getTop(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_DRAGONEGG)};
}
+ @Override
public ITexture[] getSides(byte aColor) {
return new ITexture[]{super.getSides(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_MAGIC)};
}
+ @Override
public ITexture[] getFrontActive(byte aColor) {
return new ITexture[]{super.getFrontActive(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_MAGIC_ACTIVE),
- Textures.BlockIcons.OVERLAYS_ENERGY_OUT[this.mTier]};
+ Textures.BlockIcons.OVERLAYS_ENERGY_OUT[mTier]};
}
+ @Override
public ITexture[] getBackActive(byte aColor) {
return new ITexture[]{super.getBackActive(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT_ACTIVE)};
}
+ @Override
public ITexture[] getBottomActive(byte aColor) {
return new ITexture[]{super.getBottomActive(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_MAGIC_ACTIVE)};
}
+ @Override
public ITexture[] getTopActive(byte aColor) {
return new ITexture[]{super.getTopActive(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_DRAGONEGG)};
}
+ @Override
public ITexture[] getSidesActive(byte aColor) {
return new ITexture[]{super.getSidesActive(aColor)[0], new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_MAGIC_ACTIVE)};
}
- @Override
- public int getPollution() {
- return 0;
- }
+ @Override
+ public boolean isOutputFacing(byte aSide) {
+ return aSide == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public long maxEUStore() {
+ return Math.max(getEUVar(), V[mTier] * 16000 + getMinimumStoredEU());
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (!aBaseMetaTileEntity.isServerSide()) return;
+ if (!aBaseMetaTileEntity.isAllowedToWork()) return;
+ if ((aBaseMetaTileEntity.getUniversalEnergyStored() >= aBaseMetaTileEntity.getEUCapacity())) return;
+
+ long tGeneratedEU;
+
+ if (aTick % 100 == 0) mMagicalEnergyBB.update();
+
+ // Adaptive EU Generation Ticking
+ if (aTick % mNextGenerateTickRate == 0) {
+ tGeneratedEU = generateEU();
+ if (tGeneratedEU > 0) {
+ mNoGenerationTicks = 0;
+ if (tGeneratedEU >= 2 * V[mTier])
+ mNextGenerateTickRate = (long) (1.0D / ((2.0D * (double) (V[mTier])) / (double) tGeneratedEU));
+ else mNextGenerateTickRate = 1;
+ mInventory[getStackDisplaySlot()] = new ItemStack(Blocks.fire, 1);
+ mInventory[getStackDisplaySlot()].setStackDisplayName("Generating: " + tGeneratedEU + " EU");
+ } else {
+ mInventory[getStackDisplaySlot()] = null;
+ mNoGenerationTicks += 1;
+ }
+ if (mNoGenerationTicks > 20) {
+ mNoGenerationTicks = 0;
+ mNextGenerateTickRate = 20;
+ }
+ aBaseMetaTileEntity.increaseStoredEnergyUnits(tGeneratedEU, true);
+ aBaseMetaTileEntity.setActive(aBaseMetaTileEntity.isAllowedToWork() && aBaseMetaTileEntity.getUniversalEnergyStored() >= maxEUOutput() + getMinimumStoredEU());
+ }
+ }
+
+ @Override
+ public int getPollution() {
+ return 0;
+ }
+
+ @Override
+ public GT_Recipe.GT_Recipe_Map getRecipes() {
+ return GT_Recipe.GT_Recipe_Map.sMagicFuels;
+ }
+
+ @Override
+ public int getEfficiency() {
+ return mEfficiency;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, byte aSide, ItemStack aStack) {
+ // Restrict input to disenchantable items or enchanted books
+ return (isDisenchantableItem(aStack) || isEnchantedBook(aStack));
+ }
+
+ @Override
+ public int getCapacity() {
+ return 16000;
+ }
+
+ private boolean isDisenchantableItem(ItemStack aStack) {
+ return ((aStack.isItemEnchanted()) && (aStack.getItem().getItemEnchantability() > 0));
+ }
+
+ private boolean isEnchantedBook(ItemStack aStack) {
+ return (aStack.getItem() instanceof ItemEnchantedBook);
+ }
+
+ private long generateEU() {
+ long tEU;
+
+ if ((tEU = absorbFromEgg()) > 0) return tEU;
+ if ((tEU = absorbFromEnderCrystals()) > 0) return tEU;
+ if ((tEU = absorbFromEnchantedItems()) > 0) return tEU;
+ if ((tEU = absorbFromVisNet()) > 0) return tEU;
+ if ((tEU = absorbFromEssentiaContainers()) > 0) return tEU;
+ return 0;
+ }
+
+ private long absorbFromEnchantedItems() {
+ ItemStack tStack = getBaseMetaTileEntity().getStackInSlot(getInputSlot());
+ if (tStack == null) return 0;
+ if (tStack.stackSize == 0) return 0;
+ if (!(isDisenchantableItem(tStack) || isEnchantedBook(tStack))) return 0;
+ long tEU = 0;
+ // Convert enchantments to their EU Value
+ Map<?, ?> tMap = EnchantmentHelper.getEnchantments(tStack);
+ for (Map.Entry<?, ?> e : tMap.entrySet()) {
+ if ((Integer) e.getKey() < Enchantment.enchantmentsList.length) {
+ Enchantment tEnchantment = Enchantment.enchantmentsList[(Integer) e.getKey()];
+ Integer tLevel = (Integer) e.getValue();
+ tEU += 1000000 * tLevel / (tEnchantment.getMaxLevel() * tEnchantment.getWeight());
+ }
+ }
+ if (isDisenchantableItem(tStack)) {
+ EnchantmentHelper.setEnchantments(new HashMap(), tStack);
+ tEU = tEU * getEfficiency() / 100;
+ } else if (isEnchantedBook(tStack)) {
+ tStack = new ItemStack(Items.book, 1);
+ }
+
+ // Only consume input if can store EU and push output
+ if ((getBaseMetaTileEntity().getStoredEU() + tEU) < getBaseMetaTileEntity().getEUCapacity()
+ && getBaseMetaTileEntity().addStackToSlot(getOutputSlot(), tStack)) {
+ decrStackSize(getInputSlot(), 1);
+ } else {
+ tEU = 0;
+ }
+ return tEU;
+ }
+
+ private boolean hasEgg() {
+ Block above = getBaseMetaTileEntity().getBlockOffset(0, 1, 0);
+ return isEgg(above);
+ }
+
+ private long absorbFromEgg() {
+ if (!hasEgg()) return 0;
+ if (!sAllowMultipleEggs) {
+ if (sActiveSiphon != null
+ && sActiveSiphon != this
+ && sActiveSiphon.getBaseMetaTileEntity() != null
+ && !sActiveSiphon.getBaseMetaTileEntity().isInvalidTileEntity()
+ && sActiveSiphon.isChunkLoaded()
+ && sActiveSiphon.hasEgg()) {
+ getBaseMetaTileEntity().doExplosion(Integer.MAX_VALUE);
+ } else {
+ setActiveSiphon(this);
+ }
+ }
+ return sDragonEggEnergyPerTick;
+ }
+
+ private long absorbFromEnderCrystals() {
+ if (sEnergyPerEndercrystal <= 0) return 0;
+ long tEU = 0;
+ for (GT_MetaTileEntity_MagicalEnergyAbsorber tSubscriber : sSubscribedCrystals.values()) {
+ if (tSubscriber == this) { // This Crystal is for me
+ tEU += sEnergyPerEndercrystal;
+ }
+ }
+ return tEU;
+ }
+
+ private long absorbFromVisNet() {
+ if (!THAUMCRAFT_LOADED) return 0;
+
+ long tEU;
+ IGregTechTileEntity tBaseMetaTileEntity = getBaseMetaTileEntity();
+ World tWorld = tBaseMetaTileEntity.getWorld();
+ int tX = tBaseMetaTileEntity.getXCoord();
+ int tY = tBaseMetaTileEntity.getYCoord();
+ int tZ = tBaseMetaTileEntity.getZCoord();
+
+ // Attempt to drain as much Vis as needed for max EU/t, from all primal aspects.
+ int toDrain = mMaxVisPerDrain;
+
+ for (int i = sPrimalAspects.size() - 1; i >= 0 && toDrain > 0; i--) {
+ toDrain -= VisNetHandler.drainVis(tWorld, tX, tY, tZ, sPrimalAspects.get(i), toDrain);
+ }
+
+ int drained = mMaxVisPerDrain - toDrain;
+ tEU = (long) Math.min(maxEUOutput(), (Math.pow(drained, 2) * sEnergyFromVis * getEfficiency() / 10000));
+
+ return tEU;
+ }
+
+ private long absorbFromEssentiaContainers() {
+ if (!THAUMCRAFT_LOADED) return 0;
+
+ long tEU = 0;
+
+ long tEUtoGen = getBaseMetaTileEntity().getEUCapacity() - getBaseMetaTileEntity().getUniversalEnergyStored();
+ List<Aspect> mAvailableEssentiaAspects = mMagicalEnergyBB.getAvailableAspects();
+
+ // try to drain 1 of whatever aspect available in containers within RANGE
+ for (int i = mAvailableEssentiaAspects.size() - 1; i >= 0 && tEUtoGen > 0; i--) {
+ Aspect aspect = mAvailableEssentiaAspects.get(i);
+ long tAspectEU = (sAspectsEnergy.get(aspect) * getEfficiency()) / 100;
+ if (tAspectEU <= tEUtoGen
+ && AspectSourceHelper.drainEssentia((TileEntity) getBaseMetaTileEntity(), aspect, ForgeDirection.UNKNOWN, mMagicalEnergyBB.getRange())) {
+ tEUtoGen -= tAspectEU;
+ tEU += tAspectEU;
+ }
+ }
+ return tEU;
+ }
+
+ private boolean isEgg(Block aBlock) {
+ if (aBlock == null) return false;
+ if (aBlock == Blocks.air) return false;
+ if (aBlock == Blocks.dragon_egg) return true;
+ if (aBlock instanceof BlockDragonEgg) return true;
+ return (aBlock.getUnlocalizedName().equals("tile.dragonEgg"));
+ }
+
+ private boolean isChunkLoaded() {
+ IGregTechTileEntity tBaseMetaTileEntity = getBaseMetaTileEntity();
+ int tX = tBaseMetaTileEntity.getXCoord();
+ int tY = tBaseMetaTileEntity.getYCoord();
+ World tWorld = tBaseMetaTileEntity.getWorld();
+ Chunk tChunk = tWorld.getChunkFromBlockCoords(tX, tY);
+ return tChunk.isChunkLoaded;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_MagicalEnergyAbsorber(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mMagicalEnergyBBTier", mMagicalEnergyBB.getTier());
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ mMagicalEnergyBB.setTier(aNBT.getInteger("mMagicalEnergyBBTier"));
+ }
+
+ /**
+ * Handles Bounding Box ranged operations for Magic sources
+ */
+ static class MagicalEnergyBB {
+ private GT_MetaTileEntity_MagicalEnergyAbsorber mAbsorber;
+ private MagicalEnergyBBListener mListener;
+ private int mDefaultTier;
+ private int mTier;
+ private int mMaxTier;
+ private List<UUID> mLivingCrystalIDs = new ArrayList<>();
+ private List<Aspect> mAvailableAspects;
+
+ /**
+ * @param aAbsorber user and subscriber for updated BB content
+ * @param aDefaultTier Initial tier value
+ * @param aMaxTier Maximum allowed tier
+ */
+ MagicalEnergyBB(GT_MetaTileEntity_MagicalEnergyAbsorber aAbsorber, int aDefaultTier, int aMaxTier) {
+ mAbsorber = aAbsorber;
+ mListener = aAbsorber;
+ mMaxTier = Math.max(aMaxTier > 0 ? aMaxTier : 0, aDefaultTier > 0 ? aDefaultTier : 0);
+ mDefaultTier = Math.min(aDefaultTier, mMaxTier);
+ mTier = mDefaultTier;
+ if (THAUMCRAFT_LOADED) mAvailableAspects = new ArrayList<>(Aspect.aspects.size());
+ }
+
+ int getTier() {
+ return mTier;
+ }
+
+ /**
+ * Set Bounding Box Tier within allowed bounds
+ *
+ * @param aTier new tier value
+ * @return effective new tier
+ */
+ int setTier(int aTier) {
+ if (aTier >= 0) {
+ if (aTier <= mMaxTier) {
+ mTier = aTier;
+ } else {
+ mTier = mMaxTier;
+ }
+ } else {
+ mTier = 0;
+ }
+ return mTier;
+ }
+
+ int getRange() {
+ return getRange(mTier);
+ }
+
+ int getRange(int aTier) {
+ return 1 << aTier;
+ }
+
+ int getDefaultTier() {
+ return mDefaultTier;
+ }
+
+ int getDefaultRange() {
+ return getRange(getDefaultTier());
+ }
+
+ int getMaxTier() {
+ return mMaxTier;
+ }
+
+ int getMaxRange() {
+ return getRange(getMaxTier());
+ }
+
+ private AxisAlignedBB getAxisAlignedBB() {
+ double tRange = getRange();
+ IGregTechTileEntity tBaseMetaTileEntity = mAbsorber.getBaseMetaTileEntity();
+ double tX = tBaseMetaTileEntity.getXCoord();
+ double tY = tBaseMetaTileEntity.getYCoord();
+ double tZ = tBaseMetaTileEntity.getZCoord();
+ return AxisAlignedBB.getBoundingBox(tX - tRange, tY - tRange, tZ - tRange,
+ tX + tRange, tY + tRange, tZ + tRange);
+ }
+
+ private void scanLivingCrystals() {
+ World tWorld = mAbsorber.getBaseMetaTileEntity().getWorld();
+ mLivingCrystalIDs.clear();
+ for (Object o : tWorld.getEntitiesWithinAABB(EntityEnderCrystal.class,
+ getAxisAlignedBB())) {
+ if (((EntityEnderCrystal) o).isEntityAlive()) {
+ mLivingCrystalIDs.add(((EntityEnderCrystal) o).getPersistentID());
+ }
+ }
+ }
+
+ private void scanAvailableAspects() {
+ if (!THAUMCRAFT_LOADED) return;
+ IGregTechTileEntity tBaseMetaTileEntity = mAbsorber.getBaseMetaTileEntity();
+ if (tBaseMetaTileEntity.isInvalidTileEntity()) return;
+ int tRange = getRange();
+ mAvailableAspects.clear();
+ for (int rX = -tRange; rX <= tRange; rX++) {
+ for (int rZ = -tRange; rZ <= tRange; rZ++) {
+ // rY < tRange is not a bug. See: thaumcraft.common.lib.events.EssentiaHandler.getSources()
+ for (int rY = -tRange; rY < tRange; rY++) {
+ TileEntity tTile = tBaseMetaTileEntity.getTileEntityOffset(rX, rY, rZ);
+ if (tTile instanceof IAspectSource) {
+ Set<Aspect> tAspects = ((IAspectSource) tTile).getAspects().aspects.keySet();
+ mAvailableAspects.addAll(tAspects);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @return List of Living Ender Crystal Entity IDs in range
+ */
+ List<UUID> getLivingCrystalIDs() {
+ return mLivingCrystalIDs;
+ }
+
+ /**
+ * @return List of drainable Essentia Aspects from containers in range
+ */
+ List<Aspect> getAvailableAspects() {
+ return mAvailableAspects;
+ }
+
+ /**
+ * Scan range for magic sources
+ */
+ void update() {
+ if (mAbsorber == null) return;
+ if (mAbsorber.getBaseMetaTileEntity() == null) return;
+ if (mAbsorber.getBaseMetaTileEntity().isInvalidTileEntity()) return;
+ if (mAbsorber.getBaseMetaTileEntity().getWorld() == null) return;
+ scanLivingCrystals();
+ scanAvailableAspects();
+ if (mListener != null) {
+ mListener.onMagicalEnergyBBUpdate();
+ }
+ }
+
+ void increaseTier() {
+ offsetTier(1);
+ }
+
+ void decreaseTier() {
+ offsetTier(-1);
+ }
+
+ /**
+ * Change the Bounding Box tier relatively to offset
+ * with wrapping at tier limits
+ *
+ * @param aOffset relative tier change
+ */
+ void offsetTier(int aOffset) {
+ int tNumTiers = mMaxTier + 1;
+ int tTier = (mTier + aOffset + tNumTiers) % tNumTiers;
+ int tTrueTier = setTier(tTier);
+ if (tTier != tTrueTier) {
+ GT_Log.out.format("Absorber's BB Tier set to %d was capped to %d", tTier, tTrueTier);
+ }
+ }
+ }
} \ No newline at end of file