aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDianeXD <dianelzx@outlook.com>2022-10-22 21:02:11 +0800
committerDianeXD <dianelzx@outlook.com>2022-10-22 21:02:11 +0800
commit6a36ab8fe1f8650f9fb7817c8d4c4bcdf6cb0f19 (patch)
tree8016c4e44859c41938244e72dfaecf0ff22a58ab
parenta993ec83bad6c8fddfcc72b400340c26d88683f8 (diff)
downloadGT5-Unofficial-6a36ab8fe1f8650f9fb7817c8d4c4bcdf6cb0f19.tar.gz
GT5-Unofficial-6a36ab8fe1f8650f9fb7817c8d4c4bcdf6cb0f19.tar.bz2
GT5-Unofficial-6a36ab8fe1f8650f9fb7817c8d4c4bcdf6cb0f19.zip
TFFT totally rework
-rw-r--r--src/main/java/common/Blocks.java4
-rw-r--r--src/main/java/common/CommonProxy.java4
-rw-r--r--src/main/java/common/Recipes.java50
-rw-r--r--src/main/java/common/TileEntities.java16
-rw-r--r--src/main/java/common/blocks/Block_TFFTStorageField.java88
-rw-r--r--src/main/java/common/itemBlocks/IB_TFFTStorageField.java47
-rw-r--r--src/main/java/common/tileentities/GTMTE_FluidMultiStorage.java562
-rw-r--r--src/main/java/common/tileentities/GTMTE_TFFT.java713
-rw-r--r--src/main/java/common/tileentities/GTMTE_TFFTHatch.java268
-rw-r--r--src/main/java/common/tileentities/GTMTE_TFFTMultiHatch.java217
-rw-r--r--src/main/resources/assets/kekztech/lang/en_US.lang23
-rw-r--r--src/main/resources/assets/kekztech/lang/zh_CN.lang23
12 files changed, 1165 insertions, 850 deletions
diff --git a/src/main/java/common/Blocks.java b/src/main/java/common/Blocks.java
index 2a4bf328f7..fb5b152f26 100644
--- a/src/main/java/common/Blocks.java
+++ b/src/main/java/common/Blocks.java
@@ -17,6 +17,8 @@ public class Blocks {
public static Block tfftStorageField5;
public static Block tfftMultiHatch;
+ public static Block tfftStorageField;
+
public static Block reactorChamberOFF;
public static Block reactorChamberON;
public static Block reactorControlRod;
@@ -69,6 +71,8 @@ public class Blocks {
tfftStorageField4 = Block_TFFTStorageFieldBlockT4.registerBlock();
tfftStorageField5 = Block_TFFTStorageFieldBlockT5.registerBlock();
tfftMultiHatch = Block_TFFTMultiHatch.registerBlock();
+
+ tfftStorageField = Block_TFFTStorageField.registerBlock();
}
/*private static void registerBlocks_Nuclear() {
diff --git a/src/main/java/common/CommonProxy.java b/src/main/java/common/CommonProxy.java
index bf92f6c697..464f8eab49 100644
--- a/src/main/java/common/CommonProxy.java
+++ b/src/main/java/common/CommonProxy.java
@@ -3,10 +3,12 @@ package common;
import common.items.ErrorItem;
import common.items.MetaItem_CraftingComponent;
import common.items.MetaItem_ReactorComponent;
+import common.tileentities.GTMTE_TFFTHatch;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkRegistry;
+import gregtech.api.GregTech_API;
import kekztech.GuiHandler;
import kekztech.Items;
import kekztech.KekzCore;
@@ -39,5 +41,7 @@ public class CommonProxy {
Recipes.postInit();
// Research
Researches.postInit();
+
+ if (GregTech_API.mAE2) GTMTE_TFFTHatch.registerAEIntegration();
}
}
diff --git a/src/main/java/common/Recipes.java b/src/main/java/common/Recipes.java
index 558f0b83db..64b4036d88 100644
--- a/src/main/java/common/Recipes.java
+++ b/src/main/java/common/Recipes.java
@@ -70,7 +70,7 @@ public class Recipes {
'C',
OrePrefixes.circuit.get(Materials.Data)
};
- GT_ModHandler.addCraftingRecipe(TileEntities.fms.getStackForm(1), tfft_recipe);
+ GT_ModHandler.addCraftingRecipe(TileEntities.tfft.getStackForm(1), tfft_recipe);
// Blocks
final ItemStack[] tfftcasing = {
@@ -82,7 +82,7 @@ public class Recipes {
GT_Values.RA.addAssemblerRecipe(
tfftcasing,
FluidRegistry.getFluidStack("molten.polytetrafluoroethylene", 144),
- new ItemStack(Blocks.tfftCasing, 1),
+ new ItemStack(Blocks.tfftStorageField, 1),
200,
256);
final ItemStack[] tfftstoragefield1 = {
@@ -95,7 +95,7 @@ public class Recipes {
GT_Values.RA.addAssemblerRecipe(
tfftstoragefield1,
FluidRegistry.getFluidStack("molten.glass", 144),
- new ItemStack(Blocks.tfftStorageField1, 1),
+ new ItemStack(Blocks.tfftStorageField, 1, 1),
200,
256);
final ItemStack[] tfftstoragefield2 = {
@@ -108,7 +108,7 @@ public class Recipes {
GT_Values.RA.addAssemblerRecipe(
tfftstoragefield2,
FluidRegistry.getFluidStack("molten.plastic", 576),
- new ItemStack(Blocks.tfftStorageField2, 1),
+ new ItemStack(Blocks.tfftStorageField, 1, 2),
200,
480);
final ItemStack[] tfftstoragefield3 = {
@@ -122,7 +122,7 @@ public class Recipes {
GT_Values.RA.addAssemblerRecipe(
tfftstoragefield3,
FluidRegistry.getFluidStack("molten.epoxid", 576),
- new ItemStack(Blocks.tfftStorageField3, 1),
+ new ItemStack(Blocks.tfftStorageField, 1, 3),
300,
1920);
final ItemStack[] tfftstoragefield4 = {
@@ -136,7 +136,7 @@ public class Recipes {
GT_Values.RA.addAssemblerRecipe(
tfftstoragefield4,
FluidRegistry.getFluidStack("molten.epoxid", 1152),
- new ItemStack(Blocks.tfftStorageField4, 1),
+ new ItemStack(Blocks.tfftStorageField, 1, 4),
400,
4098);
final ItemStack[] tfftstoragefield5 = {
@@ -150,11 +150,11 @@ public class Recipes {
GT_Values.RA.addAssemblerRecipe(
tfftstoragefield5,
FluidRegistry.getFluidStack("molten.epoxid", 1152),
- new ItemStack(Blocks.tfftStorageField5, 1),
+ new ItemStack(Blocks.tfftStorageField, 1, 5),
400,
6147);
// Multi Hatch
- final Object[] multi_hatch_HV = {
+ final Object[] multihatch = {
"PRP",
"UFU",
"PRP",
@@ -167,39 +167,7 @@ public class Recipes {
'F',
ItemList.Field_Generator_LV.get(1L)
};
- GT_ModHandler.addCraftingRecipe(new ItemStack(Blocks.tfftMultiHatch), multi_hatch_HV);
- final Object[] multi_hatch_IV = {
- "PRP",
- "UFU",
- "PRP",
- 'P',
- GT_OreDictUnificator.get(OrePrefixes.pipeTiny, Materials.TungstenSteel, 1),
- 'R',
- GT_OreDictUnificator.get(OrePrefixes.rotor, Materials.TungstenSteel, 1),
- 'U',
- ItemList.Electric_Pump_IV.get(1L),
- 'F',
- ItemList.Field_Generator_HV.get(1L)
- };
- GT_ModHandler.addCraftingRecipe(new ItemStack(Blocks.tfftMultiHatch), multi_hatch_IV);
- final Object[] multi_hatch_ZPM = {
- "PRP",
- "UFU",
- "PRP",
- 'P',
- GT_OreDictUnificator.get(OrePrefixes.pipeTiny, Materials.NaquadahAlloy, 1),
- 'R',
- GT_OreDictUnificator.get(OrePrefixes.rotor, Materials.NaquadahAlloy, 1),
- 'U',
- ItemList.Electric_Pump_ZPM.get(1L),
- 'F',
- ItemList.Field_Generator_IV.get(1L)
- };
- GT_ModHandler.addCraftingRecipe(new ItemStack(Blocks.tfftMultiHatch), multi_hatch_ZPM);
-
- // Conversion recipe from deprecated hatch to new one (old hatch is equal to new IV hatch)
- GT_ModHandler.addShapelessCraftingRecipe(
- TileEntities.mhIV.getStackForm(1), new ItemStack[] {new ItemStack(Blocks.tfftMultiHatch, 1)});
+ GT_ModHandler.addCraftingRecipe(TileEntities.tfftHatch.getStackForm(1), multihatch);
}
private static void registerRecipes_SOFC() {
diff --git a/src/main/java/common/TileEntities.java b/src/main/java/common/TileEntities.java
index 6253629ddb..78f27db269 100644
--- a/src/main/java/common/TileEntities.java
+++ b/src/main/java/common/TileEntities.java
@@ -1,6 +1,8 @@
package common;
import common.tileentities.*;
+import common.tileentities.GTMTE_TFFT;
+import common.tileentities.GTMTE_TFFTHatch;
import cpw.mods.fml.common.registry.GameRegistry;
public class TileEntities {
@@ -9,13 +11,12 @@ public class TileEntities {
public static GTMTE_SOFuelCellMK1 sofc1;
public static GTMTE_SOFuelCellMK2 sofc2;
// public static GTMTE_ModularNuclearReactor mdr;
- public static GTMTE_FluidMultiStorage fms;
+ public static GTMTE_TFFT tfft;
public static GTMTE_LapotronicSuperCapacitor lsc;
public static GTMTE_SpaceElevator se;
+
// Singleblocks
- public static GTMTE_TFFTMultiHatch mhHV;
- public static GTMTE_TFFTMultiHatch mhIV;
- public static GTMTE_TFFTMultiHatch mhZPM;
+ public static GTMTE_TFFTHatch tfftHatch;
public static void preInit() {
GameRegistry.registerTileEntity(TE_TFFTMultiHatch.class, "kekztech_tfftmultihatch_tile");
@@ -35,12 +36,11 @@ public class TileEntities {
sofc1 = new GTMTE_SOFuelCellMK1(13101, "multimachine.fuelcellmk1", "Solid-Oxide Fuel Cell Mk I");
sofc2 = new GTMTE_SOFuelCellMK2(13102, "multimachine.fuelcellmk2", "Solid-Oxide Fuel Cell Mk II");
// mdr = new GTMTE_ModularNuclearReactor(13103, "multimachine.nuclearreactor", "Nuclear Reactor");
- fms = new GTMTE_FluidMultiStorage(13104, "multimachine.tf_fluidtank", "T.F.F.T");
+ tfft = new GTMTE_TFFT(13104, "multimachine.tfft", "T.F.F.T");
lsc = new GTMTE_LapotronicSuperCapacitor(13106, "multimachine.supercapacitor", "Lapotronic Supercapacitor");
// se = new GTMTE_SpaceElevator(13107, "multimachine.spaceelevator", "Space Elevator");
+
// Singleblocks
- mhHV = new GTMTE_TFFTMultiHatch(13108, "machine.multihatch.0", "T.F.F.T Multi I/O Hatch [HV]", 3);
- mhIV = new GTMTE_TFFTMultiHatch(13109, "machine.multihatch.1", "T.F.F.T Multi I/O Hatch [IV]", 5);
- mhZPM = new GTMTE_TFFTMultiHatch(13110, "machine.multihatch.2", "T.F.F.T Multi I/O Hatch [ZPM]", 7);
+ tfftHatch = new GTMTE_TFFTHatch(13109, "machine.tffthatch", "T.F.F.T Multi I/O Hatch");
}
}
diff --git a/src/main/java/common/blocks/Block_TFFTStorageField.java b/src/main/java/common/blocks/Block_TFFTStorageField.java
new file mode 100644
index 0000000000..36439548af
--- /dev/null
+++ b/src/main/java/common/blocks/Block_TFFTStorageField.java
@@ -0,0 +1,88 @@
+package common.blocks;
+
+import common.itemBlocks.IB_TFFTStorageField;
+import common.tileentities.GTMTE_TFFT;
+import cpw.mods.fml.common.registry.GameRegistry;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import java.util.List;
+import kekztech.KekzCore;
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.ResourceLocation;
+
+public class Block_TFFTStorageField extends BaseGTUpdateableBlock {
+
+ private static final Block_TFFTStorageField INSTANCE = new Block_TFFTStorageField();
+ private static final int SUB_BLOCK_COUNT = GTMTE_TFFT.Field.VALUES.length + 1;
+ private static final IIcon[] textures = new IIcon[SUB_BLOCK_COUNT];
+
+ public enum TFFTCasingIcon implements IIconContainer {
+ INSTANCE;
+
+ @Override
+ public IIcon getIcon() {
+ return textures[0];
+ }
+
+ @Override
+ public IIcon getOverlayIcon() {
+ return null;
+ }
+
+ @Override
+ public ResourceLocation getTextureFile() {
+ return TextureMap.locationBlocksTexture;
+ }
+ }
+
+ // I guess glodblock won't mind
+ static {
+ GT_Utility.addTexturePage((byte) 12);
+ Textures.BlockIcons.setCasingTexture(
+ (byte) 12, (byte) 127, TextureFactory.of(Block_TFFTStorageField.TFFTCasingIcon.INSTANCE));
+ }
+
+ private Block_TFFTStorageField() {
+ super(Material.iron);
+ }
+
+ public static Block registerBlock() {
+ final String blockName = "kekztech_tfftstoragefield_block";
+ INSTANCE.setBlockName(blockName);
+ INSTANCE.setCreativeTab(CreativeTabs.tabMisc);
+ INSTANCE.setHardness(5.0f);
+ INSTANCE.setResistance(6.0f);
+ GameRegistry.registerBlock(INSTANCE, IB_TFFTStorageField.class, blockName);
+
+ return INSTANCE;
+ }
+
+ @Override
+ public void registerBlockIcons(IIconRegister ir) {
+ textures[0] = ir.registerIcon(KekzCore.MODID + ":" + "TFFTCasing");
+ for (int i = 1; i < SUB_BLOCK_COUNT; i++) {
+ textures[i] = ir.registerIcon(KekzCore.MODID + ":" + "TFFTStorageFieldBlock" + i);
+ }
+ }
+
+ @Override
+ public void getSubBlocks(Item par1, CreativeTabs par2CreativeTabs, List par3List) {
+ for (int i = 0; i < SUB_BLOCK_COUNT; i++) {
+ par3List.add(new ItemStack(par1, 1, i));
+ }
+ }
+
+ @Override
+ public IIcon getIcon(int side, int meta) {
+ return textures[meta];
+ }
+}
diff --git a/src/main/java/common/itemBlocks/IB_TFFTStorageField.java b/src/main/java/common/itemBlocks/IB_TFFTStorageField.java
new file mode 100644
index 0000000000..8e75a881f2
--- /dev/null
+++ b/src/main/java/common/itemBlocks/IB_TFFTStorageField.java
@@ -0,0 +1,47 @@
+package common.itemBlocks;
+
+import common.tileentities.GTMTE_TFFT;
+import java.text.NumberFormat;
+import java.util.List;
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+
+public class IB_TFFTStorageField extends ItemBlock {
+
+ public IB_TFFTStorageField(Block block) {
+ super(block);
+ }
+
+ @Override
+ public int getMetadata(int meta) {
+ return meta;
+ }
+
+ @Override
+ public boolean getHasSubtypes() {
+ return true;
+ }
+
+ @Override
+ public String getUnlocalizedName(ItemStack stack) {
+ return super.getUnlocalizedName() + "." + stack.getItemDamage();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void addInformation(ItemStack stack, EntityPlayer player, List lines, boolean advancedTooltips) {
+ int meta = stack.getItemDamage();
+ if (meta > 0) {
+ lines.add(StatCollector.translateToLocal("tile.kekztech_tfftstoragefield_block.desc"));
+ lines.add("Capacity: " + EnumChatFormatting.BLUE
+ + NumberFormat.getNumberInstance().format(GTMTE_TFFT.Field.VALUES[meta - 1].getCapacity())
+ + EnumChatFormatting.GRAY + " L");
+ lines.add("Power Draw: " + EnumChatFormatting.BLUE + GTMTE_TFFT.Field.VALUES[meta - 1].getCost()
+ + EnumChatFormatting.GRAY + " EU/t");
+ }
+ }
+}
diff --git a/src/main/java/common/tileentities/GTMTE_FluidMultiStorage.java b/src/main/java/common/tileentities/GTMTE_FluidMultiStorage.java
deleted file mode 100644
index df60be8362..0000000000
--- a/src/main/java/common/tileentities/GTMTE_FluidMultiStorage.java
+++ /dev/null
@@ -1,562 +0,0 @@
-package common.tileentities;
-
-import common.Blocks;
-import common.blocks.*;
-import gregtech.api.enums.Textures.BlockIcons;
-import gregtech.api.gui.GT_GUIContainer_MultiMachine;
-import gregtech.api.interfaces.ITexture;
-import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
-import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
-import gregtech.api.metatileentity.implementations.*;
-import gregtech.api.objects.GT_RenderedTexture;
-import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
-import gregtech.api.util.GT_Utility;
-import java.util.ArrayList;
-import java.util.HashSet;
-import kekztech.MultiFluidHandler;
-import net.minecraft.block.Block;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.entity.player.InventoryPlayer;
-import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.util.EnumChatFormatting;
-import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.FluidStack;
-import util.Vector3i;
-import util.Vector3ic;
-
-public class GTMTE_FluidMultiStorage extends GT_MetaTileEntity_TooltipMultiBlockBase {
-
- private static final String glassNameIC2Reinforced = "blockAlloyGlass";
- private static final Block CASING = Blocks.tfftCasing;
- private static final Block_TFFTStorageFieldBlockT1 STORAGE_FIELD1 =
- (Block_TFFTStorageFieldBlockT1) Blocks.tfftStorageField1;
- private static final Block_TFFTStorageFieldBlockT2 STORAGE_FIELD2 =
- (Block_TFFTStorageFieldBlockT2) Blocks.tfftStorageField2;
- private static final Block_TFFTStorageFieldBlockT3 STORAGE_FIELD3 =
- (Block_TFFTStorageFieldBlockT3) Blocks.tfftStorageField3;
- private static final Block_TFFTStorageFieldBlockT4 STORAGE_FIELD4 =
- (Block_TFFTStorageFieldBlockT4) Blocks.tfftStorageField4;
- private static final Block_TFFTStorageFieldBlockT5 STORAGE_FIELD5 =
- (Block_TFFTStorageFieldBlockT5) Blocks.tfftStorageField5;
- private static final int CASING_TEXTURE_ID = 176;
-
- private MultiFluidHandler mfh;
- private final HashSet<GTMTE_TFFTMultiHatch> sMultiHatches = new HashSet<>();
-
- private int runningCost = 0;
- private boolean doVoidExcess = false;
- private byte fluidSelector = 0;
-
- public GTMTE_FluidMultiStorage(int aID, String aName, String aNameRegional) {
- super(aID, aName, aNameRegional);
- }
-
- public GTMTE_FluidMultiStorage(String aName) {
- super(aName);
- }
-
- @Override
- public IMetaTileEntity newMetaEntity(IGregTechTileEntity var1) {
- return new GTMTE_FluidMultiStorage(super.mName);
- }
-
- @Override
- protected GT_Multiblock_Tooltip_Builder createTooltip() {
- final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
- tt.addMachineType("Fluid Tank")
- .addInfo("High-Tech fluid tank that can hold up to 25 different fluids!")
- .addInfo("Has 1/25th of the total capacity as capacity for each fluid.")
- .addInfo("Right clicking the controller with a screwdriver will turn on excess voiding.")
- .addInfo("Fluid storage amount and running cost depends on the storage field blocks used.")
- .addSeparator()
- .addInfo("Note on hatch locking:")
- .addInfo("Use an Integrated Circuit in the GUI slot to limit which fluid is output.")
- .addInfo("The index of a stored fluid can be obtained through the Tricorder.")
- .addSeparator()
- .beginStructureBlock(5, 9, 5, false)
- .addController("Top Center")
- .addCasingInfo("T.F.F.T. Casing", 20)
- .addOtherStructurePart("Storage Field Blocks (Tier I-V)", "Inner 3x7x3 solid pillar")
- .addOtherStructurePart("IC2 Reinforced Glass", "Outer 5x7x5 glass shell")
- .addMaintenanceHatch("Any top or bottom casing")
- .addEnergyHatch("Any top or bottom casing")
- .addInputHatch("Instead of any casing or glass, has to touch storage field block")
- .addOutputHatch("Instead of any casing or glass, has to touch storage field block")
- .addStructureInfo("You can have a bunch of hatches")
- .addOtherStructurePart(
- "Multi I/O Hatches", "Instead of any casing or glass, has to touch storage field block")
- .addStructureInfo(
- "Use MIOH with conduits or fluid storage busses to see all fluids at once. If it's fixed.")
- .addStructureInfo("Ask someone else why there's 4 versions, with 2 uncraftable ones")
- .toolTipFinisher("KekzTech");
- return tt;
- }
-
- @Override
- public ITexture[] getTexture(
- IGregTechTileEntity aBaseMetaTileEntity,
- byte aSide,
- byte aFacing,
- byte aColorIndex,
- boolean aActive,
- boolean aRedstone) {
- return aSide == aFacing
- ? new ITexture[] {
- BlockIcons.casingTexturePages[1][48],
- new GT_RenderedTexture(
- aActive
- ? BlockIcons.OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR_ACTIVE
- : BlockIcons.OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR)
- }
- : new ITexture[] {BlockIcons.casingTexturePages[1][48]};
- }
-
- public Object getClientGUI(int aID, InventoryPlayer aPlayerInventory, IGregTechTileEntity aBaseMetaTileEntity) {
- return new GT_GUIContainer_MultiMachine(
- aPlayerInventory, aBaseMetaTileEntity, this.getLocalName(), "MultiblockDisplay.png");
- }
-
- @Override
- public boolean isCorrectMachinePart(ItemStack var1) {
- return true;
- }
-
- @Override
- public boolean checkRecipe(ItemStack guiSlotItem) {
-
- super.mEfficiency = 10000 - (super.getIdealStatus() - super.getRepairStatus()) * 1000;
- super.mEfficiencyIncrease = 10000;
- super.mEUt = runningCost;
- super.mMaxProgresstime = 10;
-
- if (guiSlotItem != null && guiSlotItem.getUnlocalizedName().equals("gt.integrated_circuit")) {
- this.fluidSelector = (byte) guiSlotItem.getItemDamage();
- }
-
- // If there are no basic I/O hatches, let multi hatches handle it and skip a lot of code!
- if (sMultiHatches.size() > 0 && super.mInputHatches.size() == 0 && super.mOutputHatches.size() == 0) {
- return true;
- }
-
- // Suck in fluids
- final ArrayList<FluidStack> inputHatchFluids = super.getStoredFluids();
- if (inputHatchFluids.size() > 0) {
-
- for (FluidStack fluidStack : inputHatchFluids) {
-
- final int pushed = mfh.pushFluid(fluidStack, true);
- final FluidStack toDeplete = fluidStack.copy();
- toDeplete.amount = pushed;
- super.depleteInput(toDeplete);
- }
- }
-
- // Push out fluids
- if (guiSlotItem != null && guiSlotItem.getUnlocalizedName().equals("gt.integrated_circuit")) {
- final FluidStack storedFluid = mfh.getFluidCopy(fluidSelector);
- // Sum available output capacity
- int possibleOutput = 0;
- for (GT_MetaTileEntity_Hatch_Output outputHatch : super.mOutputHatches) {
- if (outputHatch.isFluidLocked()
- && outputHatch.getLockedFluidName().equals(storedFluid.getUnlocalizedName())) {
- possibleOutput += outputHatch.getCapacity() - outputHatch.getFluidAmount();
- } else if (outputHatch.getFluid() != null
- && outputHatch.getFluid().getUnlocalizedName().equals(storedFluid.getUnlocalizedName())) {
- possibleOutput += outputHatch.getCapacity() - outputHatch.getFluidAmount();
- } else if (outputHatch.getFluid() == null) {
- possibleOutput += outputHatch.getCapacity() - outputHatch.getFluidAmount();
- }
- }
- // Output as much as possible
- final FluidStack tempStack = storedFluid.copy();
- tempStack.amount = possibleOutput;
- tempStack.amount = mfh.pullFluid(tempStack, fluidSelector, true);
- super.addOutput(tempStack);
-
- } else {
- int tDistinct = mfh.getDistinctFluids();
- int tDistinctCount = 0;
- int tMaxDistinct = mfh.getMaxDistinctFluids();
- for (int i = 0; i < tMaxDistinct && tDistinctCount < tDistinct; i++) {
- final FluidStack storedFluidCopy = mfh.getFluidCopy(i);
- if (storedFluidCopy == null) continue;
- tDistinctCount++;
- storedFluidCopy.amount = 0;
- // Calculate how much capacity all available Output Hatches offer
- for (GT_MetaTileEntity_Hatch_Output outputHatch : super.mOutputHatches) {
- if (outputHatch.isFluidLocked()
- && outputHatch.getLockedFluidName().equals(storedFluidCopy.getUnlocalizedName())) {
- storedFluidCopy.amount += outputHatch.getCapacity() - outputHatch.getFluidAmount();
- addFluidToHatch(storedFluidCopy, outputHatch);
- } else if (outputHatch.getFluid() != null
- && outputHatch.getFluid().isFluidEqual(storedFluidCopy)) {
- storedFluidCopy.amount += outputHatch.getCapacity() - outputHatch.getFluidAmount();
- addFluidToHatch(storedFluidCopy, outputHatch);
- } else if (!outputHatch.isFluidLocked() && outputHatch.getFluid() == null) {
- storedFluidCopy.amount += outputHatch.getCapacity() - outputHatch.getFluidAmount();
- addFluidToHatch(storedFluidCopy, outputHatch);
- }
- }
- }
- }
-
- return true;
- }
-
- public void addFluidToHatch(FluidStack aFluid, GT_MetaTileEntity_Hatch_Output aHatch) {
- aFluid.amount = mfh.pullFluid(aFluid, true);
- aHatch.fill(aFluid, true);
- }
-
- @Override
- public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
- super.onPostTick(aBaseMetaTileEntity, aTick);
-
- if (mfh != null) {
- mfh.setLock(!super.getBaseMetaTileEntity().isActive());
- mfh.setFluidSelector(fluidSelector);
- mfh.setDoVoidExcess(doVoidExcess);
- }
- }
-
- public Vector3ic rotateOffsetVector(Vector3ic forgeDirection, int x, int y, int z) {
- final Vector3i offset = new Vector3i();
-
- // either direction on z-axis
- if (forgeDirection.x() == 0 && forgeDirection.z() == -1) {
- offset.x = x;
- offset.y = y;
- offset.z = z;
- }
- if (forgeDirection.x() == 0 && forgeDirection.z() == 1) {
- offset.x = -x;
- offset.y = y;
- offset.z = -z;
- }
- // either direction on x-axis
- if (forgeDirection.x() == -1 && forgeDirection.z() == 0) {
- offset.x = z;
- offset.y = y;
- offset.z = -x;
- }
- if (forgeDirection.x() == 1 && forgeDirection.z() == 0) {
- offset.x = -z;
- offset.y = y;
- offset.z = x;
- }
- // either direction on y-axis
- if (forgeDirection.y() == -1) {
- offset.x = x;
- offset.y = z;
- offset.z = y;
- }
-
- return offset;
- }
-
- @Override
- public boolean checkMachine(IGregTechTileEntity thisController, ItemStack guiSlotItem) {
- // Figure out the vector for the direction the back face of the controller is facing
- final Vector3ic forgeDirection = new Vector3i(
- ForgeDirection.getOrientation(thisController.getBackFacing()).offsetX,
- ForgeDirection.getOrientation(thisController.getBackFacing()).offsetY,
- ForgeDirection.getOrientation(thisController.getBackFacing()).offsetZ);
- int minCasingAmount = 20;
- boolean formationChecklist = true; // If this is still true at the end, machine is good to go :)
- float runningCostAcc = 0;
- double fluidCapacityAcc = 0;
-
- sMultiHatches.clear();
-
- // Front segment
- for (int X = -2; X <= 2; X++) {
- for (int Y = -2; Y <= 2; Y++) {
- if (X == 0 && Y == 0) {
- continue; // Skip controller
- }
-
- // Get next TE
- final Vector3ic offset = rotateOffsetVector(forgeDirection, X, Y, 0);
- final IGregTechTileEntity currentTE =
- thisController.getIGregTechTileEntityOffset(offset.x(), offset.y(), offset.z());
-
- // Fluid hatches should touch the storage field.
- // Maintenance/Energy hatch can go anywhere
- if (X > -2 && X < 2 && Y > -2 && Y < 2) {
- if (!super.addMaintenanceToMachineList(currentTE, CASING_TEXTURE_ID)
- && !super.addInputToMachineList(currentTE, CASING_TEXTURE_ID)
- && !super.addOutputToMachineList(currentTE, CASING_TEXTURE_ID)
- && !super.addEnergyInputToMachineList(currentTE, CASING_TEXTURE_ID)
- && !addMultiHatchToMachineList(currentTE, CASING_TEXTURE_ID)) {
-
- // If it's not a hatch, is it the right casing for this machine? Check block and block meta.
- // Also check for multi hatch
- if (thisController.getBlockOffset(offset.x(), offset.y(), offset.z()) == CASING) {
- // Seems to be valid casing. Decrement counter.
- minCasingAmount--;
- } else {
- formationChecklist = false;
- }
- }
- } else {
- if (!super.addMaintenanceToMachineList(currentTE, CASING_TEXTURE_ID)
- && !super.addEnergyInputToMachineList(currentTE, CASING_TEXTURE_ID)) {
-
- // If it's not a hatch, is it the right casing for this machine? Check block and block meta.
- if (thisController.getBlockOffset(offset.x(), offset.y(), offset.z()) == CASING) {
- // Seems to be valid casing. Decrement counter.
- minCasingAmount--;
- } else {
- formationChecklist = false;
- }
- }
- }
- }
- }
-
- // Middle seven long segment
- for (int X = -2; X <= 2; X++) {
- for (int Y = -2; Y <= 2; Y++) {
- for (int Z = -1; Z >= -7; Z--) {
- final Vector3ic offset = rotateOffsetVector(forgeDirection, X, Y, Z);
- if (X > -2 && X < 2 && Y > -2 && Y < 2) {
- if (thisController
- .getBlockOffset(offset.x(), offset.y(), offset.z())
- .getUnlocalizedName()
- .equals(STORAGE_FIELD1.getUnlocalizedName())) {
- runningCostAcc += 0.5f;
- fluidCapacityAcc += (float) Block_TFFTStorageFieldBlockT1.getCapacity();
- } else if (thisController
- .getBlockOffset(offset.x(), offset.y(), offset.z())
- .getUnlocalizedName()
- .equals(STORAGE_FIELD2.getUnlocalizedName())) {
- runningCostAcc += 1.0f;
- fluidCapacityAcc += (float) Block_TFFTStorageFieldBlockT2.getCapacity();
- } else if (thisController
- .getBlockOffset(offset.x(), offset.y(), offset.z())
- .getUnlocalizedName()
- .equals(STORAGE_FIELD3.getUnlocalizedName())) {
- runningCostAcc += 2.0f;
- fluidCapacityAcc += (float) Block_TFFTStorageFieldBlockT3.getCapacity();
- } else if (thisController
- .getBlockOffset(offset.x(), offset.y(), offset.z())
- .getUnlocalizedName()
- .equals(STORAGE_FIELD4.getUnlocalizedName())) {
- runningCostAcc += 4.0f;
- fluidCapacityAcc += (float) Block_TFFTStorageFieldBlockT4.getCapacity();
- } else if (thisController
- .getBlockOffset(offset.x(), offset.y(), offset.z())
- .getUnlocalizedName()
- .equals(STORAGE_FIELD5.getUnlocalizedName())) {
- runningCostAcc += 8.0f;
- fluidCapacityAcc += (float) Block_TFFTStorageFieldBlockT5.getCapacity();
- } else {
- formationChecklist = false;
- }
- continue;
- }
-
- // Get next TE
- final IGregTechTileEntity currentTE =
- thisController.getIGregTechTileEntityOffset(offset.x(), offset.y(), offset.z());
-
- // Corner allows only glass
- if (X == -2 && Y == -2 || X == 2 && Y == 2 || X == -2 && Y == 2 || X == 2 && Y == -2) {
- if (!(thisController
- .getBlockOffset(offset.x(), offset.y(), offset.z())
- .getUnlocalizedName()
- .equals(glassNameIC2Reinforced))) {
- formationChecklist = false;
- }
- } else {
- // Tries to add TE as either of those kinds of hatches.
- // The number is the texture index number for the texture that needs to be painted over the
- // hatch texture (TAE for GT++)
- if (!super.addInputToMachineList(currentTE, CASING_TEXTURE_ID)
- && !super.addOutputToMachineList(currentTE, CASING_TEXTURE_ID)
- && !addMultiHatchToMachineList(currentTE, CASING_TEXTURE_ID)) {
-
- // If it's not a hatch, is it the right casing for this machine? Check block and block meta.
- // Also check for multi hatch
- if (thisController.getBlockOffset(offset.x(), offset.y(), offset.z()) == CASING) {
- // Seems to be valid casing. Decrement counter.
- minCasingAmount--;
- } else if (!thisController
- .getBlockOffset(offset.x(), offset.y(), offset.z())
- .getUnlocalizedName()
- .equals(glassNameIC2Reinforced)) {
- formationChecklist = false;
- }
- }
- }
- }
- }
- }
-
- // Back segment
- for (int X = -2; X <= 2; X++) {
- for (int Y = -2; Y <= 2; Y++) {
- // Get next TE
- final Vector3ic offset = rotateOffsetVector(forgeDirection, X, Y, -8);
- final IGregTechTileEntity currentTE =
- thisController.getIGregTechTileEntityOffset(offset.x(), offset.y(), offset.z());
-
- // Fluid hatches should touch the storage field.
- // Maintenance/Energy hatch can go anywhere
- if (X > -2 && X < 2 && Y > -2 && Y < 2) {
- if (!super.addMaintenanceToMachineList(currentTE, CASING_TEXTURE_ID)
- && !super.addInputToMachineList(currentTE, CASING_TEXTURE_ID)
- && !super.addOutputToMachineList(currentTE, CASING_TEXTURE_ID)
- && !super.addEnergyInputToMachineList(currentTE, CASING_TEXTURE_ID)
- && !addMultiHatchToMachineList(currentTE, CASING_TEXTURE_ID)) {
-
- // If it's not a hatch, is it the right casing for this machine? Check block and block meta.
- if (thisController.getBlockOffset(offset.x(), offset.y(), offset.z()) == CASING) {
- // Seems to be valid casing. Decrement counter.
- minCasingAmount--;
- } else {
- formationChecklist = false;
- }
- }
- } else {
- if (!super.addMaintenanceToMachineList(currentTE, CASING_TEXTURE_ID)
- && !super.addEnergyInputToMachineList(currentTE, CASING_TEXTURE_ID)) {
-
- // If it's not a hatch, is it the right casing for this machine? Check block and block meta.
- if (thisController.getBlockOffset(offset.x(), offset.y(), offset.z()) == CASING) {
- // Seems to be valid casing. Decrement counter.
- minCasingAmount--;
- } else {
- formationChecklist = false;
- }
- }
- }
- }
- }
-
- if (this.mEnergyHatches.size() < 1) {
- formationChecklist = false;
- }
-
- if (this.mMaintenanceHatches.size() != 1) {
- formationChecklist = false;
- }
-
- if (minCasingAmount > 0) {
- formationChecklist = false;
- }
-
- if (formationChecklist) {
- runningCost = Math.round(-runningCostAcc);
- // Update MultiFluidHandler in case storage cells have been changed
- final int capacityPerFluid = (int) Math.round(fluidCapacityAcc / 25.0f);
- if (mfh == null) {
- mfh = MultiFluidHandler.newInstance(25, capacityPerFluid);
- } else {
- if (mfh.getCapacity() != capacityPerFluid) {
- mfh = MultiFluidHandler.newAdjustedInstance(mfh, capacityPerFluid);
- }
- }
- for (GTMTE_TFFTMultiHatch mh : sMultiHatches) {
- mh.setMultiFluidHandler(mfh);
- }
- }
-
- return formationChecklist;
- }
-
- public boolean addMultiHatchToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
- if (aTileEntity == null) {
- return false;
- } else {
- final IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
- if (aMetaTileEntity == null) {
- return false;
- } else if (aMetaTileEntity instanceof GTMTE_TFFTMultiHatch) {
- ((GTMTE_TFFTMultiHatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
- return this.sMultiHatches.add((GTMTE_TFFTMultiHatch) aMetaTileEntity);
- } else {
- return false;
- }
- }
- }
-
- @Override
- public void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) {
- doVoidExcess = !doVoidExcess;
- GT_Utility.sendChatToPlayer(aPlayer, doVoidExcess ? "Auto-voiding enabled" : "Auto-voiding disabled");
- }
-
- @Override
- public String[] getInfoData() {
- final ArrayList<String> ll = mfh.getInfoData();
-
- ll.add(EnumChatFormatting.YELLOW + "Operational Data:" + EnumChatFormatting.RESET);
- ll.add("Auto-voiding: " + doVoidExcess);
- ll.add("Per-Fluid Capacity: " + mfh.getCapacity() + "L");
- ll.add("Running Cost: "
- // mEUt does not naturally reflect efficiency status. Do that here.
- + ((-super.mEUt) * 10000 / Math.max(1000, super.mEfficiency)) + "EU/t");
- ll.add("Maintenance Status: "
- + ((super.getRepairStatus() == super.getIdealStatus())
- ? EnumChatFormatting.GREEN + "Working perfectly" + EnumChatFormatting.RESET
- : EnumChatFormatting.RED + "Has Problems" + EnumChatFormatting.RESET));
- ll.add("---------------------------------------------");
-
- final String[] a = new String[ll.size()];
- return ll.toArray(a);
- }
-
- @Override
- public void saveNBTData(NBTTagCompound nbt) {
- nbt = (nbt == null) ? new NBTTagCompound() : nbt;
-
- nbt.setInteger("runningCost", runningCost);
- nbt.setBoolean("doVoidExcess", doVoidExcess);
-
- nbt.setInteger("capacityPerFluid", mfh.getCapacity());
- nbt.setTag("fluids", mfh.saveNBTData(new NBTTagCompound()));
-
- super.saveNBTData(nbt);
- }
-
- @Override
- public void loadNBTData(NBTTagCompound nbt) {
- nbt = (nbt == null) ? new NBTTagCompound() : nbt;
-
- runningCost = nbt.getInteger("runningCost");
- doVoidExcess = nbt.getBoolean("doVoidExcess");
-
- mfh = MultiFluidHandler.loadNBTData(nbt);
- for (GTMTE_TFFTMultiHatch mh : sMultiHatches) {
- mh.setMultiFluidHandler(mfh);
- }
- super.loadNBTData(nbt);
- }
-
- @Override
- public boolean isGivingInformation() {
- return true;
- }
-
- @Override
- public int getMaxEfficiency(ItemStack var1) {
- return 10000;
- }
-
- @Override
- public int getPollutionPerTick(ItemStack var1) {
- return 0;
- }
-
- @Override
- public int getDamageToComponent(ItemStack var1) {
- return 0;
- }
-
- @Override
- public boolean explodesOnComponentBreak(ItemStack var1) {
- return false;
- }
-}
diff --git a/src/main/java/common/tileentities/GTMTE_TFFT.java b/src/main/java/common/tileentities/GTMTE_TFFT.java
new file mode 100644
index 0000000000..c107d76896
--- /dev/null
+++ b/src/main/java/common/tileentities/GTMTE_TFFT.java
@@ -0,0 +1,713 @@
+package common.tileentities;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static gregtech.api.enums.GT_HatchElement.*;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static java.lang.Math.min;
+
+import com.github.bartimaeusnek.bartworks.API.BorosilicateGlass;
+import com.gtnewhorizon.structurelib.StructureLibAPI;
+import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+import common.Blocks;
+import gregtech.api.enums.Textures;
+import gregtech.api.fluid.FluidTankGT;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.IGT_HatchAdder;
+import gregtech.common.items.GT_IntegratedCircuit_Item;
+import java.math.BigInteger;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTankInfo;
+
+public class GTMTE_TFFT extends GT_MetaTileEntity_EnhancedMultiBlockBase<GTMTE_TFFT> {
+
+ public enum Field {
+ T1(1_000_000L, 2), // LV
+ T2(4_000_000L, 3), // MV
+ T3(16_000_000L, 5), // HV
+ T4(64_000_000L, 13), // EV
+ T5(256_000_000L, 89), // IV
+
+ T6(2_048_000_000L, 233), // LuV
+ T7(131_072_000_000L, 1597), // UV
+ T8(8_388_608_000_000L, 28657), // UEV
+ T9(536_870_912_000_000L, 514229), // UIV
+
+ T10(1_099_511_627_776_000_000L, 0); // UXV
+
+ public static final GTMTE_TFFT.Field[] VALUES = values();
+ private final long capacity;
+ private final int cost;
+
+ Field(long capacity, int cost) {
+ this.capacity = capacity;
+ this.cost = cost;
+ }
+
+ public long getCapacity() {
+ return capacity;
+ }
+
+ public int getCost() {
+ return cost;
+ }
+ }
+
+ private enum TFFTMultiHatch implements IHatchElement<GTMTE_TFFT> {
+ INSTANCE;
+
+ @Override
+ public List<? extends Class<? extends IMetaTileEntity>> mteClasses() {
+ return Collections.singletonList(GTMTE_TFFT.class);
+ }
+
+ @Override
+ public IGT_HatchAdder<? super GTMTE_TFFT> adder() {
+ return GTMTE_TFFT::addMultiHatchToMachineList;
+ }
+
+ @Override
+ public long count(GTMTE_TFFT t) {
+ return t.tfftHatch == null ? 0 : 1;
+ }
+ }
+
+ private static final IIconContainer TEXTURE_TFFT = new Textures.BlockIcons.CustomIcon("iconsets/TFFT");
+ private static final IIconContainer TEXTURE_TFFT_ACTIVE =
+ new Textures.BlockIcons.CustomIcon("iconsets/TFFT_ACTIVE");
+ private static final IIconContainer TEXTURE_TFFT_ACTIVE_GLOW =
+ new Textures.BlockIcons.CustomIcon("iconsets/TFFT_ACTIVE_GLOW");
+ private static final int CASING_TEXTURE_ID_1 = (12 << 7) | 127;
+ private static final int CASING_TEXTURE_ID_2 = 176;
+
+ private static final Block TFFT_FIELD = Blocks.tfftStorageField;
+ private static final Item TFFT_FIELD_ITEM = Item.getItemFromBlock(TFFT_FIELD);
+ public static final int MAX_DISTINCT_FLUIDS = 25;
+ private static final BigInteger MAX_CAPACITY =
+ BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(25));
+ private static final int CASING_META = 0;
+ private static final int MIN_CASING_AMOUNT = 20;
+ private static final int MAX_LAYER_AMOUNT = 13;
+ private static final int DEFAULT_LAYER_AMOUNT = 3;
+
+ private static final String STRUCTURE_PIECE_TOP = "top";
+ private static final String STRUCTURE_PIECE_MID = "mid";
+ private static final String STRUCTURE_PIECE_BOTTOM = "bottom";
+ private static final IStructureDefinition<GTMTE_TFFT> STRUCTURE_DEFINITION =
+ IStructureDefinition.<GTMTE_TFFT>builder()
+ .addShape(
+ STRUCTURE_PIECE_TOP,
+ transpose(new String[][] {{"ccccc"}, {"cCCCc"}, {"cC~Cc"}, {"cCCCc"}, {"ccccc"}}))
+ .addShape(
+ STRUCTURE_PIECE_MID,
+ transpose(new String[][] {{"gGGGg"}, {"GfffG"}, {"GfffG"}, {"GfffG"}, {"gGGGg"}}))
+ .addShape(
+ STRUCTURE_PIECE_BOTTOM,
+ transpose(new String[][] {{"ccccc"}, {"cCCCc"}, {"cCCCc"}, {"cCCCc"}, {"ccccc"}}))
+ .addElement(
+ 'c',
+ buildHatchAdder(GTMTE_TFFT.class)
+ .atLeast(Energy, Maintenance)
+ .casingIndex(CASING_TEXTURE_ID_1)
+ .dot(1)
+ .buildAndChain(
+ onElementPass(te -> te.casingAmount++, ofBlock(TFFT_FIELD, CASING_META))))
+ .addElement(
+ 'C',
+ buildHatchAdder(GTMTE_TFFT.class)
+ .casingIndex(CASING_TEXTURE_ID_1)
+ .atLeast(
+ Energy,
+ Maintenance,
+ InputHatch.or(TFFTMultiHatch.INSTANCE),
+ OutputHatch.or(TFFTMultiHatch.INSTANCE))
+ .dot(2)
+ .buildAndChain(
+ onElementPass(te -> te.casingAmount++, ofBlock(TFFT_FIELD, CASING_META))))
+ .addElement(
+ 'G',
+ buildHatchAdder(GTMTE_TFFT.class)
+ .atLeast(
+ InputHatch.or(TFFTMultiHatch.INSTANCE),
+ OutputHatch.or(TFFTMultiHatch.INSTANCE))
+ .casingIndex(CASING_TEXTURE_ID_2)
+ .dot(3)
+ .buildAndChain(
+ ofBlockUnlocalizedName("IC2", "blockAlloyGlass", 0, true),
+ ofBlockUnlocalizedName("Thaumcraft", "blockCosmeticOpaque", 2, false),
+ BorosilicateGlass.ofBoroGlassAnyTier()))
+ .addElement(
+ 'g',
+ ofChain(
+ ofBlockUnlocalizedName("IC2", "blockAlloyGlass", 0, true),
+ ofBlockUnlocalizedName("Thaumcraft", "blockCosmeticOpaque", 2, false),
+ BorosilicateGlass.ofBoroGlassAnyTier()))
+ .addElement('f', ofChain(new IStructureElement<GTMTE_TFFT>() {
+ @Override
+ public boolean check(GTMTE_TFFT t, World world, int x, int y, int z) {
+ Block worldBlock = world.getBlock(x, y, z);
+ int meta = worldBlock.getDamageValue(world, x, y, z);
+ if (TFFT_FIELD != worldBlock || meta == 0) return false;
+ t.FIELDS[meta - 1]++;
+ return true;
+ }
+
+ private int getHint(ItemStack stack) {
+ return Math.min(Field.VALUES.length, ChannelDataAccessor.getChannelData(stack, "field"));
+ }
+
+ @Override
+ public boolean spawnHint(GTMTE_TFFT t, World world, int x, int y, int z, ItemStack trigger) {
+ StructureLibAPI.hintParticle(world, x, y, z, TFFT_FIELD, getHint(trigger));
+ return true;
+ }
+
+ @Override
+ public boolean placeBlock(GTMTE_TFFT t, World world, int x, int y, int z, ItemStack trigger) {
+ world.setBlock(x, y, z, TFFT_FIELD, getHint(trigger), 3);
+ return true;
+ }
+ }))
+ .build();
+
+ public final FluidTankGT[] STORE = new FluidTankGT[MAX_DISTINCT_FLUIDS];
+
+ {
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ STORE[i] = new FluidTankGT(0);
+ }
+ }
+
+ private final int[] FIELDS = new int[Field.VALUES.length];
+
+ private BigInteger capacity = BigInteger.ZERO;
+ private long capacityPerFluid = 0L;
+ private int casingAmount = 0;
+ private int runningCost = 0;
+
+ private boolean locked = true;
+ private boolean doVoidExcess = false;
+ private byte fluidSelector = -1;
+
+ private GTMTE_TFFTHatch tfftHatch = null;
+
+ public GTMTE_TFFT(String aName) {
+ super(aName);
+ }
+
+ public GTMTE_TFFT(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ @Override
+ public IStructureDefinition<GTMTE_TFFT> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GTMTE_TFFT(super.mName);
+ }
+
+ @Override
+ public ITexture[] getTexture(
+ IGregTechTileEntity aBaseMetaTileEntity,
+ byte aSide,
+ byte aFacing,
+ byte aColorIndex,
+ boolean aActive,
+ boolean aRedstone) {
+ if (aSide == aFacing) {
+ if (aActive)
+ return new ITexture[] {
+ Textures.BlockIcons.getCasingTextureForId(CASING_TEXTURE_ID_1),
+ TextureFactory.builder()
+ .addIcon(TEXTURE_TFFT_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(TEXTURE_TFFT_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build()
+ };
+ return new ITexture[] {
+ Textures.BlockIcons.getCasingTextureForId(CASING_TEXTURE_ID_1),
+ TextureFactory.builder().addIcon(TEXTURE_TFFT).extFacing().build()
+ };
+ }
+ return new ITexture[] {Textures.BlockIcons.getCasingTextureForId(CASING_TEXTURE_ID_1)};
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fluid Tank")
+ .addInfo("High-Tech fluid tank that can hold up to 25 different fluids!")
+ .addInfo("Has 1/25th of the total capacity as capacity for each fluid.")
+ .addInfo("Right clicking the controller with a screwdriver will turn on excess voiding.")
+ .addInfo("Fluid storage amount and running cost depends on the storage field blocks used.")
+ .addSeparator()
+ .addInfo("Note on hatch locking:")
+ .addInfo("Use an Integrated Circuit in the GUI slot to limit which fluid is output.")
+ .addInfo("The index of a stored fluid can be obtained through the Tricorder.")
+ .addSeparator()
+ .beginVariableStructureBlock(5, 5, 5, 15, 5, 5, false)
+ .addController("Top Center")
+ .addCasingInfo("T.F.F.T Casing", MIN_CASING_AMOUNT)
+ .addOtherStructurePart("Storage Field Blocks (Tier I-X)", "Inner 3xhx3 solid pillar")
+ .addStructureInfo("Energy hatch is not required when running cost is 0")
+ .addOtherStructurePart(
+ "Borosilicate Glass(any)/Warded Glass/Reinforced Glass", "Outer 5xhx5 glass shell")
+ .addMaintenanceHatch("Any top or bottom casing")
+ .addEnergyHatch("Any top or bottom casing")
+ .addInputHatch("Instead of any casing or glass, has to touch storage field block")
+ .addOutputHatch("Instead of any casing or glass, has to touch storage field block")
+ .addStructureInfo("You can have a bunch of hatches")
+ .addOtherStructurePart(
+ "Multi I/O Hatches", "Instead of any casing or glass, has to touch storage field block")
+ .addStructureInfo("Use MIOH with conduits or fluid storage busses to see all fluids at once.")
+ .toolTipFinisher("KekzTech");
+ return tt;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ int layer = min(stackSize.stackSize + DEFAULT_LAYER_AMOUNT, MAX_LAYER_AMOUNT + 1);
+ buildPiece(STRUCTURE_PIECE_TOP, stackSize, hintsOnly, 2, 2, 0);
+ for (int i = -1; i >= 1 - layer; i--) buildPiece(STRUCTURE_PIECE_MID, stackSize, hintsOnly, 2, 2, i);
+ buildPiece(STRUCTURE_PIECE_BOTTOM, stackSize, hintsOnly, 2, 2, -layer);
+ }
+
+ // @Override
+ // public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ // if (mMachine) return -1;
+ // int build = survivialBuildPiece(STRUCTURE_PIECE_TOP, stackSize, 2, 2, 0, elementBudget, env, false, true);
+ // if (build >= 0) return build;
+ // int layer = min(stackSize.stackSize + DEFAULT_LAYER_AMOUNT, MAX_LAYER_AMOUNT + 1);
+ // for (int i = -1; i >= 1 - layer; i--) {
+ // survivialBuildPiece(STRUCTURE_PIECE_MID, stackSize, 2, 2, i, elementBudget, env, false, true);
+ // if (build >= 0) return build;
+ // }
+ // return survivialBuildPiece(STRUCTURE_PIECE_BOTTOM, stackSize, 2, 2, -layer, elementBudget, env, false,
+ // true);
+ // }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public void clearHatches() {
+ super.clearHatches();
+ if (tfftHatch != null) {
+ tfftHatch.unbind();
+ tfftHatch = null;
+ }
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ Arrays.fill(FIELDS, 0);
+
+ this.capacity = BigInteger.ZERO;
+ this.capacityPerFluid = 0L;
+ this.casingAmount = 0;
+ this.runningCost = 0;
+
+ if (!checkPiece(STRUCTURE_PIECE_TOP, 2, 2, 0)) return false;
+
+ int layer = 1;
+ while (checkPiece(STRUCTURE_PIECE_MID, 2, 2, -layer)) layer++;
+ if (layer - 1 > MAX_LAYER_AMOUNT || layer - 1 < DEFAULT_LAYER_AMOUNT) return false;
+ if (!checkPiece(STRUCTURE_PIECE_BOTTOM, 2, 2, -layer)) return false;
+ if (casingAmount >= MIN_CASING_AMOUNT
+ && (tfftHatch != null || (!mInputHatches.isEmpty() && !mOutputHatches.isEmpty()))
+ && mInputHatches.size() + mOutputHatches.size() <= MAX_DISTINCT_FLUIDS * 2
+ && mMaintenanceHatches.size() == 1) {
+ BigInteger tempCap = BigInteger.ZERO;
+ for (int i = 0; i < this.FIELDS.length; i++) {
+ tempCap = tempCap.add(
+ BigInteger.valueOf(Field.VALUES[i].getCapacity()).multiply(BigInteger.valueOf(this.FIELDS[i])));
+ this.runningCost += Field.VALUES[i].getCost() * this.FIELDS[i];
+ }
+ this.setCapacity(tempCap);
+
+ if (tfftHatch != null) tfftHatch.bind(this);
+
+ return !mEnergyHatches.isEmpty() ^ this.runningCost == 0;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean checkRecipe(ItemStack itemStack) {
+ mEfficiency = getCurrentEfficiency(null);
+ mEfficiencyIncrease = 10000;
+ mEUt = this.runningCost;
+ mMaxProgresstime = 20;
+
+ this.fluidSelector = (itemStack != null && itemStack.getItem() instanceof GT_IntegratedCircuit_Item)
+ ? (byte) itemStack.getItemDamage()
+ : -1;
+
+ // Suck in fluids
+ final ArrayList<FluidStack> inputFluids = getStoredFluids();
+
+ if (!inputFluids.isEmpty()) {
+ for (FluidStack aFluid : inputFluids) {
+ final FluidStack toDeplete = aFluid.copy();
+ toDeplete.amount = this.pull(aFluid, true);
+ depleteInput(toDeplete);
+ }
+ }
+
+ // Push out fluids
+ if (!this.mOutputHatches.isEmpty()) {
+ final FluidTankGT sFluid = this.getSelectedFluid();
+ boolean isFluidSelected = this.fluidSelector != -1;
+
+ if (!isFluidSelected || !sFluid.isEmpty()) {
+ for (GT_MetaTileEntity_Hatch_Output tHatch : this.mOutputHatches) {
+ int hatchCapacity = tHatch.getCapacity();
+ int hatchAmount = tHatch.getFluidAmount();
+ int remaining = hatchCapacity - hatchAmount;
+
+ if (remaining <= 0) continue;
+
+ final FluidStack tFluid = tHatch.getFluid();
+
+ String lockedFluidName = tHatch.getLockedFluidName() == null ? "" : tHatch.getLockedFluidName();
+ String tFluidName = tFluid == null ? "" : tFluid.getFluid().getName();
+
+ boolean isFluidLocked = tHatch.isFluidLocked();
+ boolean isFluidEmpty = tFluid == null || tHatch.getFluidAmount() == 0;
+
+ if (isFluidLocked && !this.contains(lockedFluidName)) continue;
+ if (!isFluidEmpty && !this.contains(tFluid)) continue;
+ if ((isFluidLocked && !isFluidEmpty) && !lockedFluidName.equals(tFluidName)) continue;
+
+ if (isFluidSelected) {
+ if (isFluidLocked && !lockedFluidName.equals(sFluid.name())) continue;
+ if (!isFluidEmpty && !sFluid.contains(tFluid)) continue;
+
+ tHatch.fill(this.push(sFluid.get(remaining), true), true);
+ } else if (isFluidLocked) {
+ if (!isFluidEmpty
+ && !lockedFluidName.equals(tFluid.getFluid().getName())) continue;
+
+ FluidStack aFluid = FluidRegistry.getFluidStack(lockedFluidName, remaining);
+ tHatch.fill(this.push(aFluid, true), true);
+ } else if (isFluidEmpty) {
+ if (this.firstNotNull() != null) tHatch.fill(this.push(hatchCapacity, true), true);
+ } else {
+ tHatch.fill(this.push(new FluidStack(tFluid, remaining), true), true);
+ }
+ }
+ }
+ }
+
+ if (this.mEUt > 0) this.mEUt = -this.mEUt;
+
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isServerSide()) this.locked = !aBaseMetaTileEntity.isActive();
+ }
+
+ @Override
+ public String[] getInfoData() {
+ ArrayList<String> ll = new ArrayList<>();
+ NumberFormat nf = NumberFormat.getNumberInstance();
+
+ ll.add(EnumChatFormatting.YELLOW + "Stored Fluids:" + EnumChatFormatting.RESET);
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ FluidTankGT tank = STORE[i];
+ if (tank.isEmpty()) {
+ ll.add(MessageFormat.format("{0} - {1}: {2}L ({3}%)", i, "NULL", 0, 0));
+ } else {
+ String localizedName = STORE[i].get().getLocalizedName();
+ String amount = nf.format(STORE[i].amount());
+ String percentage =
+ capacityPerFluid > 0 ? String.valueOf(STORE[i].amount() * 100 / capacityPerFluid) : "";
+
+ ll.add(MessageFormat.format("{0} - {1}: {2}L ({3}%)", i, localizedName, amount, percentage));
+ }
+ }
+ ll.add(EnumChatFormatting.YELLOW + "Operational Data:" + EnumChatFormatting.RESET);
+ ll.add("Used Capacity: " + nf.format(getStoredAmount()) + "L");
+ ll.add("Total Capacity: " + nf.format(capacity) + "L");
+ ll.add("Per-Fluid Capacity: " + nf.format(capacityPerFluid) + "L");
+ ll.add("Running Cost: " + getActualEnergyUsage() + "EU/t");
+ ll.add("Auto-voiding: " + doVoidExcess);
+ ll.add("Maintenance Status: "
+ + ((getRepairStatus() == getIdealStatus())
+ ? EnumChatFormatting.GREEN + "Working perfectly" + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + "Has Problems" + EnumChatFormatting.RESET));
+ ll.add("---------------------------------------------");
+
+ return ll.toArray(new String[0]);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setByteArray("capacity", capacity.toByteArray());
+ aNBT.setBoolean("doVoidExcess", doVoidExcess);
+ aNBT.setInteger("runningCost", runningCost);
+ aNBT.setBoolean("lockFluid", locked);
+ aNBT.setByte("fluidSelector", fluidSelector);
+
+ NBTTagCompound fluidNBT = new NBTTagCompound();
+ aNBT.setTag("STORE", fluidNBT);
+
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ STORE[i].writeToNBT(fluidNBT, String.valueOf(i));
+ }
+
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ this.setCapacity(new BigInteger(aNBT.getByteArray("capacity")));
+ this.setDoVoidExcess(aNBT.getBoolean("doVoidExcess"));
+ this.runningCost = aNBT.getInteger("runningCost");
+ this.locked = aNBT.getBoolean("lockFluid");
+ this.fluidSelector = aNBT.getByte("fluidSelector");
+
+ NBTTagCompound fluidNBT = (NBTTagCompound) aNBT.getTag("STORE");
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ STORE[i].readFromNBT(fluidNBT, String.valueOf(i));
+ }
+
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack stack) {
+ return 10000;
+ }
+
+ @Override
+ public int getPollutionPerTick(ItemStack stack) {
+ return 0;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack stack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack stack) {
+ return false;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ super.onScrewdriverRightClick(aSide, aPlayer, aX, aY, aZ);
+ this.setDoVoidExcess(!doVoidExcess);
+ GT_Utility.sendChatToPlayer(aPlayer, "Auto-voiding " + (this.doVoidExcess ? "enabled" : "disabled"));
+ }
+
+ private boolean addMultiHatchToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity != null) {
+ final IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity instanceof GTMTE_TFFTHatch) {
+ if (this.tfftHatch != null) return false;
+ this.tfftHatch = (GTMTE_TFFTHatch) aMetaTileEntity;
+ this.tfftHatch.updateTexture(aBaseCasingIndex);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int pull(FluidStack aFluid, boolean doPull) {
+ if (locked) return 0;
+ int index = getFluidPosition(aFluid);
+ if (index >= 0) {
+ return STORE[index].fill(aFluid, doPull);
+ } else if (fluidCount() < MAX_DISTINCT_FLUIDS) {
+ return STORE[getNullSlot()].setCapacity(capacityPerFluid).fill(aFluid, doPull);
+ }
+ return 0;
+ }
+
+ public long pull(FluidStack aFluid, long amount, boolean doPull) {
+ if (locked) return 0;
+ int index = getFluidPosition(aFluid);
+ if (index >= 0) {
+ FluidTankGT tank = STORE[index];
+ if (doPull) return tank.add(amount);
+ return doVoidExcess
+ ? amount
+ : tank.amount() + amount > tank.capacity() ? tank.capacity() - tank.amount() : amount;
+ } else if (fluidCount() < MAX_DISTINCT_FLUIDS) {
+ FluidTankGT tank = STORE[getNullSlot()];
+ if (doPull) return tank.add(amount, aFluid);
+ return doVoidExcess ? amount : Math.min(amount, tank.capacity());
+ }
+ return 0;
+ }
+
+ public FluidStack push(FluidStack aFluid, boolean doPush) {
+ if (locked) return null;
+ int index = getFluidPosition(aFluid);
+ if (index < 0) return null;
+ return STORE[index].drain(aFluid.amount, doPush);
+ }
+
+ public FluidStack push(int amount, boolean doPush) {
+ if (locked) return null;
+ int index = firstNotNullSlot();
+ if (index < 0) return null;
+ return STORE[index].drain(amount, doPush);
+ }
+
+ public long push(FluidStack aFluid, long amount, boolean doPush) {
+ if (locked) return 0;
+ int index = getFluidPosition(aFluid);
+ if (index < 0) return 0;
+ if (doPush) return STORE[index].remove(amount);
+ return STORE[index].amount(amount);
+ }
+
+ public long getCapacityPerFluid() {
+ return this.capacityPerFluid;
+ }
+
+ public void setCapacity(BigInteger capacity) {
+ if (capacity.compareTo(MAX_CAPACITY) > 0) {
+ this.capacity = MAX_CAPACITY;
+ this.capacityPerFluid = Long.MAX_VALUE;
+ } else {
+ this.capacity = capacity;
+ this.capacityPerFluid =
+ capacity.divide(BigInteger.valueOf(MAX_DISTINCT_FLUIDS)).longValue();
+ }
+
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ FluidTankGT tank = STORE[i];
+ if (tank.setCapacity(capacityPerFluid).amount() > capacityPerFluid) {
+ STORE[i] = new FluidTankGT(tank.get(), capacityPerFluid, capacityPerFluid);
+ }
+ }
+ }
+
+ public int fluidCount() {
+ int tCount = 0;
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ if (!STORE[i].isEmpty()) tCount++;
+ }
+ return tCount;
+ }
+
+ public int getFluidPosition(String fluidName) {
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ if (!STORE[i].isEmpty() && STORE[i].name().equals(fluidName)) return i;
+ }
+ return -1;
+ }
+
+ public int getFluidPosition(FluidStack aFluid) {
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ if (STORE[i].contains(aFluid)) return i;
+ }
+ return -1;
+ }
+
+ public int getNullSlot() {
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ if (STORE[i].isEmpty()) return i;
+ }
+ return -1;
+ }
+
+ public boolean contains(String fluidName) {
+ return getFluidPosition(fluidName) >= 0;
+ }
+
+ public boolean contains(FluidStack aFluid) {
+ return getFluidPosition(aFluid) >= 0;
+ }
+
+ public int firstNotNullSlot() {
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ if (!STORE[i].isEmpty()) return i;
+ }
+ return -1;
+ }
+
+ public FluidTankGT firstNotNull() {
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ if (!STORE[i].isEmpty()) return STORE[i];
+ }
+ return null;
+ }
+
+ public BigInteger getStoredAmount() {
+ BigInteger amount = BigInteger.ZERO;
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ amount = amount.add(BigInteger.valueOf(STORE[i].amount()));
+ }
+ return amount;
+ }
+
+ public byte getFluidSelector() {
+ return fluidSelector;
+ }
+
+ public FluidTankGT getSelectedFluid() {
+ return fluidSelector != -1 ? STORE[fluidSelector] : null;
+ }
+
+ public void setDoVoidExcess(boolean doVoidExcess) {
+ this.doVoidExcess = doVoidExcess;
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ STORE[i].setVoidExcess(doVoidExcess);
+ }
+ }
+
+ public FluidTankInfo[] getTankInfo() {
+ FluidTankInfo[] info = new FluidTankInfo[MAX_DISTINCT_FLUIDS];
+ for (int i = 0; i < MAX_DISTINCT_FLUIDS; i++) {
+ STORE[i].getFluid(); //
+ info[i] = STORE[i].getInfo();
+ }
+ return info;
+ }
+}
diff --git a/src/main/java/common/tileentities/GTMTE_TFFTHatch.java b/src/main/java/common/tileentities/GTMTE_TFFTHatch.java
new file mode 100644
index 0000000000..bf79bb877e
--- /dev/null
+++ b/src/main/java/common/tileentities/GTMTE_TFFTHatch.java
@@ -0,0 +1,268 @@
+package common.tileentities;
+
+import appeng.api.AEApi;
+import appeng.api.config.AccessRestriction;
+import appeng.api.config.Actionable;
+import appeng.api.networking.security.BaseActionSource;
+import appeng.api.storage.*;
+import appeng.api.storage.data.IAEFluidStack;
+import appeng.api.storage.data.IItemList;
+import appeng.util.item.AEFluidStack;
+import appeng.util.item.FluidList;
+import cpw.mods.fml.common.Optional;
+import gregtech.api.enums.Textures;
+import gregtech.api.fluid.FluidTankGT;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.BaseMetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.render.TextureFactory;
+import java.util.HashMap;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTankInfo;
+
+@Optional.Interface(iface = "appeng.api.storage.IMEMonitor", modid = "appliedenergistics2", striprefs = true)
+public class GTMTE_TFFTHatch extends GT_MetaTileEntity_Hatch implements IMEMonitor<IAEFluidStack> {
+
+ @Optional.Interface(
+ iface = "appeng.api.storage.IExternalStorageHandler",
+ modid = "appliedenergistics2",
+ striprefs = true)
+ private static class AE2TFFTHatchHandler implements IExternalStorageHandler {
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel channel, BaseActionSource mySrc) {
+ return channel == StorageChannel.FLUIDS
+ && te instanceof BaseMetaTileEntity
+ && ((BaseMetaTileEntity) te).getMetaTileEntity() instanceof GTMTE_TFFTHatch;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public IMEInventory getInventory(
+ TileEntity te, ForgeDirection d, StorageChannel channel, BaseActionSource src) {
+ if (channel == StorageChannel.FLUIDS) {
+ return ((GTMTE_TFFTHatch) (((BaseMetaTileEntity) te).getMetaTileEntity()));
+ }
+ return null;
+ }
+ }
+
+ private static final Textures.BlockIcons.CustomIcon TEXTURE_TFFT_HATCH =
+ new Textures.BlockIcons.CustomIcon("iconsets/TFFT_HATCH");
+
+ private HashMap<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> listeners = new HashMap<>();
+ private GTMTE_TFFT controller;
+
+ public GTMTE_TFFTHatch(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, 3, 0, "All-in-one access for the T.F.F.T");
+ }
+
+ public GTMTE_TFFTHatch(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 0, aDescription, aTextures);
+ }
+
+ @Override
+ public boolean isFacingValid(byte aFacing) {
+ return true;
+ }
+
+ @Override
+ public ITexture[] getTexture(
+ IGregTechTileEntity aBaseMetaTileEntity,
+ byte aSide,
+ byte aFacing,
+ byte aColorIndex,
+ boolean aActive,
+ boolean aRedstone) {
+ return super.getTexture(aBaseMetaTileEntity, aSide, aFacing, aColorIndex, aActive, aRedstone);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] {
+ aBaseTexture,
+ TextureFactory.of(Textures.BlockIcons.OVERLAY_PIPE_IN),
+ TextureFactory.builder().addIcon(TEXTURE_TFFT_HATCH).extFacing().build()
+ };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] {
+ aBaseTexture,
+ TextureFactory.of(Textures.BlockIcons.OVERLAY_PIPE_IN),
+ TextureFactory.builder().addIcon(TEXTURE_TFFT_HATCH).extFacing().build()
+ };
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GTMTE_TFFTHatch(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
+ return (controller != null) ? controller.pull(resource, doFill) : 0;
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
+ if (controller != null) {
+ final FluidTankGT sFluid = controller.getSelectedFluid();
+ if (controller.getFluidSelector() == -1 || (sFluid != null && sFluid.contains(resource))) {
+ return controller.push(resource, doDrain);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
+ if (controller != null) {
+ final FluidTankGT sFluid = controller.getSelectedFluid();
+ if (controller.getFluidSelector() == -1) return controller.push(maxDrain, doDrain);
+ if (sFluid != null) return controller.push(sFluid.get(maxDrain), doDrain);
+ }
+ return null;
+ }
+
+ @Override
+ public FluidTankInfo[] getTankInfo(ForgeDirection from) {
+ return (controller != null) ? controller.getTankInfo() : null;
+ }
+
+ public void bind(GTMTE_TFFT controller) {
+ this.controller = controller;
+ }
+
+ public void unbind() {
+ this.controller = null;
+ }
+
+ @Optional.Method(modid = "appliedenergistics2")
+ public static void registerAEIntegration() {
+ AEApi.instance().registries().externalStorage().addExternalStorageInterface(new AE2TFFTHatchHandler());
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public IItemList<IAEFluidStack> getAvailableItems(IItemList out) {
+ if (controller != null) {
+ for (int i = 0; i < GTMTE_TFFT.MAX_DISTINCT_FLUIDS; i++) {
+ if (!controller.STORE[i].isEmpty()) {
+ IAEFluidStack s = AEFluidStack.create(controller.STORE[i].get());
+ s.setStackSize(controller.STORE[i].amount());
+ out.add(s);
+ }
+ }
+ }
+ return out;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public IItemList<IAEFluidStack> getStorageList() {
+ IItemList<IAEFluidStack> fluidList = new FluidList();
+ if (controller != null) {
+ for (int i = 0; i < GTMTE_TFFT.MAX_DISTINCT_FLUIDS; i++) {
+ if (!controller.STORE[i].isEmpty()) {
+ IAEFluidStack s = AEFluidStack.create(controller.STORE[i].get());
+ s.setStackSize(controller.STORE[i].amount());
+ fluidList.add(s);
+ }
+ }
+ }
+ return fluidList;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public void addListener(IMEMonitorHandlerReceiver<IAEFluidStack> l, Object verificationToken) {
+ if (listeners == null) listeners = new HashMap<>();
+ listeners.put(l, verificationToken);
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public void removeListener(IMEMonitorHandlerReceiver<IAEFluidStack> l) {
+ if (listeners == null) listeners = new HashMap<>();
+ listeners.remove(l);
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public AccessRestriction getAccess() {
+ return AccessRestriction.READ_WRITE;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public boolean isPrioritized(IAEFluidStack input) {
+ if (controller == null || input == null) return false;
+ return controller.contains(input.getFluidStack()) || controller.fluidCount() < GTMTE_TFFT.MAX_DISTINCT_FLUIDS;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public boolean canAccept(IAEFluidStack input) {
+ if (controller == null || input == null) return false;
+ return controller.contains(input.getFluidStack()) || controller.fluidCount() < GTMTE_TFFT.MAX_DISTINCT_FLUIDS;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public int getPriority() {
+ return 0;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public int getSlot() {
+ return 0;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public boolean validForPass(int i) {
+ return true;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public IAEFluidStack injectItems(IAEFluidStack input, Actionable mode, BaseActionSource src) {
+ final FluidStack inputStack = input.getFluidStack();
+ if (inputStack == null) return null;
+ if (controller == null || getBaseMetaTileEntity() == null) return input;
+ if (mode != Actionable.SIMULATE) getBaseMetaTileEntity().markDirty();
+ long amount = controller.pull(input.getFluidStack(), input.getStackSize(), mode != Actionable.SIMULATE);
+ if (amount == 0) return input;
+ if (amount == input.getStackSize()) return null;
+ IAEFluidStack result = AEFluidStack.create(input.getFluidStack());
+ result.setStackSize(input.getStackSize() - amount);
+ return result;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public IAEFluidStack extractItems(IAEFluidStack request, Actionable mode, BaseActionSource src) {
+ if (controller == null || getBaseMetaTileEntity() == null) return null;
+ if (mode != Actionable.SIMULATE) getBaseMetaTileEntity().markDirty();
+ long amount = controller.push(request.getFluidStack(), request.getStackSize(), mode != Actionable.SIMULATE);
+ if (amount == 0) return null;
+ if (amount == request.getStackSize()) return request.copy();
+ IAEFluidStack result = AEFluidStack.create(request.getFluidStack());
+ result.setStackSize(amount);
+ return result;
+ }
+
+ @Override
+ @Optional.Method(modid = "appliedenergistics2")
+ public StorageChannel getChannel() {
+ return StorageChannel.FLUIDS;
+ }
+}
diff --git a/src/main/java/common/tileentities/GTMTE_TFFTMultiHatch.java b/src/main/java/common/tileentities/GTMTE_TFFTMultiHatch.java
deleted file mode 100644
index 8c992f8cb0..0000000000
--- a/src/main/java/common/tileentities/GTMTE_TFFTMultiHatch.java
+++ /dev/null
@@ -1,217 +0,0 @@
-package common.tileentities;
-
-import gregtech.api.enums.Textures;
-import gregtech.api.interfaces.ITexture;
-import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
-import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
-import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
-import gregtech.api.objects.GT_RenderedTexture;
-import gregtech.api.util.GT_Utility;
-import java.util.HashMap;
-import kekztech.MultiFluidHandler;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.tileentity.TileEntity;
-import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.FluidStack;
-import net.minecraftforge.fluids.FluidTankInfo;
-import net.minecraftforge.fluids.IFluidHandler;
-
-public class GTMTE_TFFTMultiHatch extends GT_MetaTileEntity_Hatch {
-
- private static final HashMap<Integer, Integer> vals = new HashMap<>();
-
- static {
- vals.put(3, 2000);
- vals.put(5, 20000);
- vals.put(7, 200000);
- }
-
- private static final int INV_SLOT_COUNT = 2;
-
- private MultiFluidHandler mfh;
- private boolean outputting = false;
-
- public GTMTE_TFFTMultiHatch(int aID, String aName, String aNameRegional, int aTier) {
- super(aID, aName, aNameRegional, aTier, INV_SLOT_COUNT, new String[] {
- "All-in-one access for the T.F.F.T",
- "Right-click with a screwdriver to toggle auto-output",
- "Throughput: " + vals.get(aTier) + "L/s per fluid"
- });
- }
-
- public GTMTE_TFFTMultiHatch(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
- super(aName, aTier, INV_SLOT_COUNT, aDescription, aTextures);
- }
-
- public GTMTE_TFFTMultiHatch(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
- super(aName, aTier, INV_SLOT_COUNT, aDescription, aTextures);
- }
-
- public void setMultiFluidHandler(MultiFluidHandler mfh) {
- this.mfh = mfh;
- }
-
- @Override
- public void saveNBTData(NBTTagCompound aNBT) {
- super.saveNBTData(aNBT);
- aNBT.setBoolean("outputting", outputting);
- }
-
- @Override
- public void loadNBTData(NBTTagCompound aNBT) {
- super.loadNBTData(aNBT);
- outputting = aNBT.getBoolean("outputting");
- }
-
- @Override
- public ITexture[] getTexturesActive(ITexture aBaseTexture) {
- // return new ITexture[]{aBaseTexture, new GT_RenderedTexture(GTTexture.MULTI_HATCH_ON)};
- return new ITexture[] {aBaseTexture, new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_PIPE_STEEL)};
- }
-
- @Override
- public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
- // return new ITexture[]{aBaseTexture, new GT_RenderedTexture(GTTexture.MULTI_HATCH_OFF)};
- return new ITexture[] {
- aBaseTexture, new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_PIPE_POLYTETRAFLUOROETHYLENE)
- };
- }
-
- @Override
- public IMetaTileEntity newMetaEntity(IGregTechTileEntity iGregTechTileEntity) {
- return new GTMTE_TFFTMultiHatch(super.mName, super.mTier, super.mDescriptionArray, super.mTextures);
- }
-
- @Override
- public boolean isMachineBlockUpdateRecursive() {
- return false;
- }
-
- @Override
- public void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) {
- outputting = !outputting;
- GT_Utility.sendChatToPlayer(aPlayer, outputting ? "Auto-output enabled" : "Auto-output disabled");
- }
-
- @Override
- public int getCapacity() {
- return (mfh != null) ? mfh.getCapacity() : 0;
- }
-
- public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
- super.onPreTick(aBaseMetaTileEntity, aTick);
- if (aBaseMetaTileEntity.isServerSide() && mfh != null) {
- if (outputting && (aTick % 20 == 0)) {
- doAutoOutputPerSecond(aBaseMetaTileEntity);
- }
- }
- }
-
- /**
- * Handle the Multi Hatch's auto-output feature. Should be called once per second only.
- * @param aBaseMetaTileEntity
- * this MetaTileEntity
- */
- private void doAutoOutputPerSecond(IGregTechTileEntity aBaseMetaTileEntity) {
- final ForgeDirection outSide = ForgeDirection.getOrientation(aBaseMetaTileEntity.getFrontFacing());
- final TileEntity adjacentTE =
- aBaseMetaTileEntity.getTileEntityOffset(outSide.offsetX, outSide.offsetY, outSide.offsetZ);
- if (adjacentTE instanceof IFluidHandler) {
- final IFluidHandler adjFH = (IFluidHandler) adjacentTE;
- // Cycle through fluids
- for (int i = 0; i < mfh.getDistinctFluids(); i++) {
- final FluidStack fluidCopy = mfh.getFluidCopy(i);
- // Make sure the adjacent IFluidHandler can accept this fluid
- if (adjFH.canFill(outSide.getOpposite(), fluidCopy.getFluid())) {
-
- // Limit to output rate
- fluidCopy.amount = Math.min(fluidCopy.amount, vals.get(super.mTier));
-
- // Test how much can be drawn
- fluidCopy.amount = mfh.pullFluid(fluidCopy, false);
-
- // Test how much can be filled (and fill if possible)
- fluidCopy.amount = adjFH.fill(outSide.getOpposite(), fluidCopy, true);
-
- // Actually deplete storage
- mfh.pullFluid(fluidCopy, true);
- }
- }
- }
- }
-
- @Override
- public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
- return (mfh != null) ? mfh.pushFluid(resource, doFill) : 0;
- }
-
- @Override
- public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
- return (mfh != null) ? new FluidStack(resource.getFluid(), mfh.pullFluid(resource, doDrain)) : null;
- }
-
- /**
- * Drains fluid out of 0th internal tank.
- * If the TFFT Controller contains an Integrated Circuit, drain fluid
- * from the slot equal to the circuit configuration.
- *
- * @param from
- * Orientation the fluid is drained to.
- * @param maxDrain
- * Maximum amount of fluid to drain.
- * @param doDrain
- * If false, drain will only be simulated.
- * @return FluidStack representing the Fluid and amount that was (or would have been, if
- * simulated) drained.
- */
- @Override
- public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
- if (mfh != null) {
- final FluidStack drain = mfh.getFluidCopy(0);
- if (drain != null) {
- // If there's no integrated circuit in the T.F.F.T. controller, output slot 0
- final byte selectedSlot = (mfh.getSelectedFluid() == -1) ? 0 : mfh.getSelectedFluid();
-
- return new FluidStack(
- drain.getFluid(),
- mfh.pullFluid(new FluidStack(drain.getFluid(), maxDrain), selectedSlot, doDrain));
- }
- }
- return null;
- }
-
- @Override
- public FluidTankInfo[] getTankInfo(ForgeDirection from) {
- if (mfh == null) return null;
- FluidStack[] fluids = mfh.getAllFluids();
- int length = fluids.length;
- int maxCapcity = mfh.getCapacity();
- FluidTankInfo[] tankInfo = new FluidTankInfo[length];
- for (int i = 0; i < length; i++) {
- tankInfo[i] = new FluidTankInfo(fluids[i], maxCapcity);
- }
- return tankInfo;
- }
-
- @Override
- public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, byte aSide, ItemStack aStack) {
- return false;
- }
-
- @Override
- public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, byte aSide, ItemStack aStack) {
- return false;
- }
-
- @Override
- public boolean canTankBeFilled() {
- return true;
- }
-
- @Override
- public boolean canTankBeEmptied() {
- return true;
- }
-}
diff --git a/src/main/resources/assets/kekztech/lang/en_US.lang b/src/main/resources/assets/kekztech/lang/en_US.lang
index 13fc831a0c..0e0245ae8e 100644
--- a/src/main/resources/assets/kekztech/lang/en_US.lang
+++ b/src/main/resources/assets/kekztech/lang/en_US.lang
@@ -110,17 +110,18 @@ item.kekztech_crafting_item.14.name=YSZ Ceramic Plate
item.kekztech_crafting_item.15.name=GDC Ceramic Plate
# -------- TFFT: Structure Blocks
-tile.kekztech_tfftcasingblock_block.name=T.F.F.T Casing
-tile.kekztech_tfftstoragefieldblock1_block.name=T.F.F.T Storage Field Block (Tier I)
-tile.kekztech_tfftstoragefieldblock1_block.0.desc=This is not a fluid tank
-tile.kekztech_tfftstoragefieldblock2_block.name=T.F.F.T Storage Field Block (Tier II)
-tile.kekztech_tfftstoragefieldblock3_block.name=T.F.F.T Storage Field Block (Tier III)
-tile.kekztech_tfftstoragefieldblock4_block.name=T.F.F.T Storage Field Block (Tier IV)
-tile.kekztech_tfftstoragefieldblock5_block.name=T.F.F.T Storage Field Block (Tier V)
-tile.kekztech_tfftmultihatch_block.0.name=[DEPRECATED] T.F.F.T Multi-Fluid I/O Hatch (Tier I)
-tile.kekztech_tfftmultihatch_block.1.name=[DEPRECATED] T.F.F.T Multi-Fluid I/O Hatch (Tier II)
-tile.kekztech_tfftmultihatch_block.2.name=[DEPRECATED] T.F.F.T Multi-Fluid I/O Hatch (Tier III)
-tile.kekztech_tfftmultihatch_block.0.desc=Put in crafting field to change to update
+tile.kekztech_tfftstoragefield_block.0.name=T.F.F.T Casing
+tile.kekztech_tfftstoragefield_block.1.name=T.F.F.T Storage Field Block (Tier I)
+tile.kekztech_tfftstoragefield_block.2.name=T.F.F.T Storage Field Block (Tier II)
+tile.kekztech_tfftstoragefield_block.3.name=T.F.F.T Storage Field Block (Tier III)
+tile.kekztech_tfftstoragefield_block.4.name=T.F.F.T Storage Field Block (Tier IV)
+tile.kekztech_tfftstoragefield_block.5.name=T.F.F.T Storage Field Block (Tier V)
+tile.kekztech_tfftstoragefield_block.6.name=T.F.F.T Storage Field Block (Tier VI)
+tile.kekztech_tfftstoragefield_block.7.name=T.F.F.T Storage Field Block (Tier VII)
+tile.kekztech_tfftstoragefield_block.8.name=T.F.F.T Storage Field Block (Tier VIII)
+tile.kekztech_tfftstoragefield_block.9.name=T.F.F.T Storage Field Block (Tier IX)
+tile.kekztech_tfftstoragefield_block.10.name=T.F.F.T Storage Field Block (Tier X)
+tile.kekztech_tfftstoragefield_block.desc=This is not a fluid tank
# -------- Item Proxy: Structure Blocks
tile.kekztech_itemproxycable_block.name=Item Proxy Network Cable
diff --git a/src/main/resources/assets/kekztech/lang/zh_CN.lang b/src/main/resources/assets/kekztech/lang/zh_CN.lang
index cfc135b863..d7ec936c48 100644
--- a/src/main/resources/assets/kekztech/lang/zh_CN.lang
+++ b/src/main/resources/assets/kekztech/lang/zh_CN.lang
@@ -110,17 +110,18 @@ item.kekztech_crafting_item.14.name=钇锆陶瓷板
item.kekztech_crafting_item.15.name=钆铈陶瓷板
# -------- TFFT: Structure Blocks
-tile.kekztech_tfftcasingblock_block.name=T.F.F.T机械方块
-tile.kekztech_tfftstoragefieldblock1_block.name=T.F.F.T存储库方块(T1)
-tile.kekztech_tfftstoragefieldblock1_block.0.desc=这不是流体储罐
-tile.kekztech_tfftstoragefieldblock2_block.name=T.F.F.T存储库方块(T2)
-tile.kekztech_tfftstoragefieldblock3_block.name=T.F.F.T存储库方块(T3)
-tile.kekztech_tfftstoragefieldblock4_block.name=T.F.F.T存储库方块(T4)
-tile.kekztech_tfftstoragefieldblock5_block.name=T.F.F.T存储库方块(T5)
-tile.kekztech_tfftmultihatch_block.0.name=[已弃用]T.F.F.T输入/输出仓(Tier I)
-tile.kekztech_tfftmultihatch_block.1.name=[已弃用]T.F.F.T输入/输出仓(Tier II)
-tile.kekztech_tfftmultihatch_block.2.name=[已弃用]T.F.F.T输入/输出仓(Tier III)
-tile.kekztech_tfftmultihatch_block.0.desc=放入合成栏以升级
+tile.kekztech_tfftstoragefield_block.0.name=T.F.F.T机械方块
+tile.kekztech_tfftstoragefield_block.1.name=T.F.F.T存储库方块(T1)
+tile.kekztech_tfftstoragefield_block.2.name=T.F.F.T存储库方块(T2)
+tile.kekztech_tfftstoragefield_block.3.name=T.F.F.T存储库方块(T3)
+tile.kekztech_tfftstoragefield_block.4.name=T.F.F.T存储库方块(T4)
+tile.kekztech_tfftstoragefield_block.5.name=T.F.F.T存储库方块(T5)
+tile.kekztech_tfftstoragefield_block.6.name=T.F.F.T存储库方块(T6)
+tile.kekztech_tfftstoragefield_block.7.name=T.F.F.T存储库方块(T7)
+tile.kekztech_tfftstoragefield_block.8.name=T.F.F.T存储库方块(T8)
+tile.kekztech_tfftstoragefield_block.9.name=T.F.F.T存储库方块(T9)
+tile.kekztech_tfftstoragefield_block.10.name=T.F.F.T存储库方块(T10)
+tile.kekztech_tfftstoragefield_block.desc=这不是流体储罐
# -------- Item Proxy: Structure Blocks
tile.kekztech_itemproxycable_block.name=物流网络线缆