diff options
Diffstat (limited to 'src/main/java/gtnhlanth/common/tileentity')
12 files changed, 3833 insertions, 0 deletions
diff --git a/src/main/java/gtnhlanth/common/tileentity/MTEDigester.java b/src/main/java/gtnhlanth/common/tileentity/MTEDigester.java new file mode 100644 index 0000000000..9e1fc65c1b --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/MTEDigester.java @@ -0,0 +1,240 @@ +package gtnhlanth.common.tileentity; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose; +import static gregtech.api.enums.HatchElement.Energy; +import static gregtech.api.enums.HatchElement.InputBus; +import static gregtech.api.enums.HatchElement.InputHatch; +import static gregtech.api.enums.HatchElement.Maintenance; +import static gregtech.api.enums.HatchElement.Muffler; +import static gregtech.api.enums.HatchElement.OutputBus; +import static gregtech.api.enums.HatchElement.OutputHatch; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages; +import static gregtech.api.util.GTStructureUtility.buildHatchAdder; +import static gregtech.api.util.GTStructureUtility.ofCoil; + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.util.ForgeDirection; + +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; + +import gregtech.api.GregTechAPI; +import gregtech.api.enums.HeatingCoilLevel; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.metatileentity.implementations.MTEEnhancedMultiBlockBase; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.recipe.check.CheckRecipeResult; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.api.util.OverclockCalculator; +import gtnhlanth.api.recipe.LanthanidesRecipeMaps; +import gtnhlanth.util.DescTextLocalization; + +public class MTEDigester extends MTEEnhancedMultiBlockBase<MTEDigester> implements ISurvivalConstructable { + + protected int casingAmount = 0; + protected int height = 0; + + private HeatingCoilLevel heatLevel; + + private final IStructureDefinition<MTEDigester> multiDefinition = StructureDefinition.<MTEDigester>builder() + .addShape( + mName, + transpose( + new String[][] { { " ", " ttttt ", " t---t ", " t---t ", " t---t ", " ttttt ", " " }, + { " ttt ", " t---t ", "t-----t", "t-----t", "t-----t", " t---t ", " ttt " }, + { " tccct ", "tc---ct", "c-----c", "c-----c", "c-----c", "tc---ct", " tccct " }, + { " tt~tt ", "thhhhht", "thsssht", "thsssht", "thsssht", "thhhhht", " ttttt " }, })) + + .addElement( + 't', + buildHatchAdder(MTEDigester.class) + .atLeast(InputHatch, OutputHatch, InputBus, OutputBus, Maintenance, Energy, Muffler) + .casingIndex(47) + .dot(1) + .buildAndChain(GregTechAPI.sBlockCasings4, 0)) + .addElement('h', ofBlock(GregTechAPI.sBlockCasings1, 11)) + .addElement('s', ofBlock(GregTechAPI.sBlockCasings4, 1)) + .addElement('c', ofCoil(MTEDigester::setCoilLevel, MTEDigester::getCoilLevel)) + .build(); + + public MTEDigester(String name) { + super(name); + } + + public MTEDigester(int id, String name, String nameRegional) { + super(id, name, nameRegional); + } + + @Override + public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { + return checkPiece(mName, 3, 3, 0) && !mMufflerHatches.isEmpty() && mMaintenanceHatches.size() == 1; + } + + @Override + public boolean isCorrectMachinePart(ItemStack aStack) { + return true; + } + + public HeatingCoilLevel getCoilLevel() { + return this.heatLevel; + } + + public void setCoilLevel(HeatingCoilLevel level) { + this.heatLevel = level; + } + + @Override + public RecipeMap<?> getRecipeMap() { + return LanthanidesRecipeMaps.digesterRecipes; + } + + @Override + protected ProcessingLogic createProcessingLogic() { + return new ProcessingLogic() { + + @Nonnull + @Override + protected OverclockCalculator createOverclockCalculator(@Nonnull GTRecipe recipe) { + return super.createOverclockCalculator(recipe).enablePerfectOC(); + } + + @Override + protected @Nonnull CheckRecipeResult validateRecipe(@Nonnull GTRecipe recipe) { + return recipe.mSpecialValue <= MTEDigester.this.getCoilLevel() + .getHeat() ? CheckRecipeResultRegistry.SUCCESSFUL + : CheckRecipeResultRegistry.insufficientHeat(recipe.mSpecialValue); + } + + }; + } + + @Override + public boolean supportsVoidProtection() { + return true; + } + + @Override + public boolean supportsInputSeparation() { + return true; + } + + @Override + public boolean supportsBatchMode() { + return true; + } + + @Override + public boolean supportsSingleRecipeLocking() { + return true; + } + + @Override + public int getMaxEfficiency(ItemStack itemStack) { + return 10000; + } + + @Override + public int getPollutionPerTick(ItemStack aStack) { + return 20; + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity arg0) { + return new MTEDigester(this.mName); + } + + @Override + public void construct(ItemStack itemStack, boolean b) { + buildPiece(mName, itemStack, b, 3, 3, 0); + } + + @Override + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + if (mMachine) return -1; + return survivialBuildPiece(mName, stackSize, 3, 3, 0, elementBudget, env, false, true); + } + + @Override + public String[] getStructureDescription(ItemStack arg0) { + return DescTextLocalization.addText("Digester.hint", 6); + } + + public ITexture[] getTexture(IGregTechTileEntity te, ForgeDirection side, ForgeDirection facing, int colorIndex, + boolean active, boolean redstone) { + + // Oil Cracker textures cuz I'm lazy + + if (side == facing) { + if (active) return new ITexture[] { casingTexturePages[0][47], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW) + .extFacing() + .glow() + .build() }; + return new ITexture[] { casingTexturePages[0][47], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_GLOW) + .extFacing() + .glow() + .build() }; + } + return new ITexture[] { casingTexturePages[0][47] }; + } + + @Override + protected MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Digester") + .addInfo("Controller block for the Digester") + .addInfo("Input ores and fluid, output water.") + .addInfo(DescTextLocalization.BLUEPRINT_INFO) + .addSeparator() + .addController("Front bottom") + .addInputHatch("Hint block with dot 1") + .addInputBus("Hint block with dot 1") + .addOutputHatch("Hint block with dot 1") + .addOutputBus("Hint block with dot 1") + .addMaintenanceHatch("Hint block with dot 1") + .addMufflerHatch("Hint block with dot 1") + .toolTipFinisher("GTNH: Lanthanides"); + return tt; + } + + @Override + public IStructureDefinition<MTEDigester> getStructureDefinition() { + return multiDefinition; + } + + @Override + public boolean explodesOnComponentBreak(ItemStack arg0) { + // TODO Auto-generated method stub + return false; + } + + @Override + public int getDamageToComponent(ItemStack arg0) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/src/main/java/gtnhlanth/common/tileentity/MTEDissolutionTank.java b/src/main/java/gtnhlanth/common/tileentity/MTEDissolutionTank.java new file mode 100644 index 0000000000..7d5a64b579 --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/MTEDissolutionTank.java @@ -0,0 +1,264 @@ +package gtnhlanth.common.tileentity; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlockAdder; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose; +import static gregtech.api.enums.HatchElement.Energy; +import static gregtech.api.enums.HatchElement.InputBus; +import static gregtech.api.enums.HatchElement.InputHatch; +import static gregtech.api.enums.HatchElement.Maintenance; +import static gregtech.api.enums.HatchElement.OutputBus; +import static gregtech.api.enums.HatchElement.OutputHatch; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages; +import static gregtech.api.util.GTStructureUtility.buildHatchAdder; + +import java.util.Arrays; +import java.util.List; + +import javax.annotation.Nonnull; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.NotNull; + +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; + +import bartworks.common.loaders.ItemRegistry; +import gregtech.api.GregTechAPI; +import gregtech.api.interfaces.ISecondaryDescribable; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.metatileentity.implementations.MTEEnhancedMultiBlockBase; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.recipe.check.CheckRecipeResult; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; +import gregtech.api.recipe.check.SimpleCheckRecipeResult; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.MultiblockTooltipBuilder; +import gtnhlanth.api.recipe.LanthanidesRecipeMaps; +import gtnhlanth.util.DescTextLocalization; + +public class MTEDissolutionTank extends MTEEnhancedMultiBlockBase<MTEDissolutionTank> + implements ISurvivalConstructable, ISecondaryDescribable { + + private final IStructureDefinition<MTEDissolutionTank> multiDefinition = StructureDefinition + .<MTEDissolutionTank>builder() + .addShape( + mName, + transpose( + new String[][] { { " sss ", "sssss", "sssss", "sssss", " sss " }, + { "sgggs", "g---g", "g---g", "g---g", "sgggs" }, { "sgggs", "g---g", "g---g", "g---g", "sgggs" }, + { "ss~ss", "shhhs", "shhhs", "shhhs", "sssss" }, { "s s", " ", " ", " ", "s s" } })) + .addElement( + 's', + buildHatchAdder(MTEDissolutionTank.class) + .atLeast(InputHatch, OutputHatch, InputBus, OutputBus, Maintenance, Energy) + .casingIndex(49) + .dot(1) + .buildAndChain(GregTechAPI.sBlockCasings4, 1)) + .addElement('h', ofBlock(GregTechAPI.sBlockCasings1, 11)) + .addElement('g', ofBlockAdder(MTEDissolutionTank::addGlass, ItemRegistry.bw_glasses[0], 1)) + .build(); + + public MTEDissolutionTank(String name) { + super(name); + } + + public MTEDissolutionTank(int id, String name, String nameRegional) { + super(id, name, nameRegional); + } + + @Override + public IStructureDefinition<MTEDissolutionTank> getStructureDefinition() { + return multiDefinition; + } + + @Override + public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { + return checkPiece(mName, 2, 3, 0) && mMaintenanceHatches.size() == 1; + } + + @Override + public boolean isCorrectMachinePart(ItemStack aStack) { + return true; + } + + private boolean addGlass(Block block, int meta) { + return block == ItemRegistry.bw_glasses[0]; + } + + @Override + public RecipeMap<?> getRecipeMap() { + return LanthanidesRecipeMaps.dissolutionTankRecipes; + } + + @Override + protected ProcessingLogic createProcessingLogic() { + return new ProcessingLogic() { + + @NotNull + @Override + protected CheckRecipeResult onRecipeStart(@Nonnull GTRecipe recipe) { + if (!checkRatio(recipe, Arrays.asList(inputFluids))) { + criticalStopMachine(); + return SimpleCheckRecipeResult.ofFailurePersistOnShutdown("dissolution_ratio"); + } + return CheckRecipeResultRegistry.SUCCESSFUL; + } + + }; + } + + @Override + public boolean supportsVoidProtection() { + return true; + } + + @Override + public boolean supportsInputSeparation() { + return true; + } + + @Override + public boolean supportsBatchMode() { + return true; + } + + @Override + public boolean supportsSingleRecipeLocking() { + return true; + } + + private boolean checkRatio(GTRecipe tRecipe, List<FluidStack> tFluidInputs) { + FluidStack majorGenericFluid = tRecipe.mFluidInputs[0]; + FluidStack minorGenericFluid = tRecipe.mFluidInputs[1]; + + int majorAmount; + int minorAmount; + + FluidStack fluidInputOne = tFluidInputs.get(0); + FluidStack fluidInputTwo = tFluidInputs.get(1); + + if (fluidInputOne.getUnlocalizedName() + .equals(majorGenericFluid.getUnlocalizedName())) { + if (fluidInputTwo.getUnlocalizedName() + .equals(minorGenericFluid.getUnlocalizedName())) { + // majorInput = fluidInputOne; + majorAmount = fluidInputOne.amount; + // minorInput = fluidInputTwo; + minorAmount = fluidInputTwo.amount; + // GTLog.out.print("in first IF"); + } else return false; // No valid other input + + } else if (fluidInputTwo.getUnlocalizedName() + .equals(majorGenericFluid.getUnlocalizedName())) { + if (fluidInputOne.getUnlocalizedName() + .equals(minorGenericFluid.getUnlocalizedName())) { + // majorInput = fluidInputTwo; + majorAmount = fluidInputTwo.amount; + // minorInput = fluidInputOne; + minorAmount = fluidInputOne.amount; + // GTLog.out.print("in second if"); + } else return false; + + } else return false; + + return majorAmount / tRecipe.mSpecialValue == minorAmount; + } + + @Override + public int getMaxEfficiency(ItemStack itemStack) { + return 10000; + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity arg0) { + return new MTEDissolutionTank(this.mName); + } + + @Override + public void construct(ItemStack itemStack, boolean b) { + buildPiece(mName, itemStack, b, 2, 3, 0); + } + + @Override + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + if (mMachine) return -1; + return survivialBuildPiece(mName, stackSize, 2, 3, 0, elementBudget, env, false, true); + } + + @Override + public String[] getStructureDescription(ItemStack arg0) { + return DescTextLocalization.addText("DissolutionTank.hint", 4); + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity te, ForgeDirection side, ForgeDirection facing, int colorIndex, + boolean active, boolean redstone) { + + if (side == facing) { + if (active) return new ITexture[] { casingTexturePages[0][49], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW) + .extFacing() + .glow() + .build() }; + return new ITexture[] { casingTexturePages[0][49], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_GLOW) + .extFacing() + .glow() + .build() }; + } + return new ITexture[] { casingTexturePages[0][49] }; + } + + @Override + protected MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Dissolution Tank") + .addInfo("Controller block for the Dissolution Tank") + .addInfo("Input Water and Fluid, output Fluid") + .addInfo("You must input the Fluids at the correct Ratio") + .addInfo(DescTextLocalization.BLUEPRINT_INFO) + .addSeparator() + .addController("Front bottom") + .addInputHatch("Hint block with dot 1") + .addInputBus("Hint block with dot 1") + .addOutputHatch("Hint block with dot 1") + .addOutputBus("Hint block with dot 1") + .addMaintenanceHatch("Hint block with dot 1") + .toolTipFinisher("GTNH: Lanthanides"); + + return tt; + } + + @Override + public boolean explodesOnComponentBreak(ItemStack arg0) { + return false; + } + + @Override + public int getDamageToComponent(ItemStack arg0) { + return 0; + } +} diff --git a/src/main/java/gtnhlanth/common/tileentity/MTELINAC.java b/src/main/java/gtnhlanth/common/tileentity/MTELINAC.java new file mode 100644 index 0000000000..78ea9c7846 --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/MTELINAC.java @@ -0,0 +1,749 @@ +package gtnhlanth.common.tileentity; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static gregtech.api.enums.GTValues.VN; +import static gregtech.api.enums.HatchElement.Energy; +import static gregtech.api.enums.HatchElement.InputHatch; +import static gregtech.api.enums.HatchElement.Maintenance; +import static gregtech.api.enums.HatchElement.OutputHatch; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages; +import static gregtech.api.util.GTStructureUtility.buildHatchAdder; +import static gtnhlanth.util.DescTextLocalization.addDotText; + +import java.util.ArrayList; +import java.util.Objects; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; + +import com.gtnewhorizon.structurelib.StructureLib; +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; + +import bartworks.API.BorosilicateGlass; +import gregtech.api.GregTechAPI; +import gregtech.api.enums.GTValues; +import gregtech.api.enums.TickTime; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.metatileentity.implementations.MTEEnhancedMultiBlockBase; +import gregtech.api.metatileentity.implementations.MTEHatchEnergy; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTUtility; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.api.util.shutdown.ShutDownReason; +import gregtech.api.util.shutdown.SimpleShutDownReason; +import gtnhlanth.common.beamline.BeamInformation; +import gtnhlanth.common.beamline.BeamLinePacket; +import gtnhlanth.common.beamline.Particle; +import gtnhlanth.common.hatch.MTEHatchInputBeamline; +import gtnhlanth.common.hatch.MTEHatchOutputBeamline; +import gtnhlanth.common.register.LanthItemList; +import gtnhlanth.common.tileentity.recipe.beamline.BeamlineRecipeLoader; +import gtnhlanth.util.DescTextLocalization; +import gtnhlanth.util.Util; + +public class MTELINAC extends MTEEnhancedMultiBlockBase<MTELINAC> implements ISurvivalConstructable { + + private static final IStructureDefinition<MTELINAC> STRUCTURE_DEFINITION; + + protected static final String STRUCTURE_PIECE_BASE = "base"; + protected static final String STRUCTURE_PIECE_LAYER = "layer"; + protected static final String STRUCTURE_PIECE_END = "end"; + + private byte glassTier; + + private boolean onEndInnerLayer = false; + + private int machineTemp = 0; // Coolant temperature + + private ArrayList<MTEHatchInputBeamline> mInputBeamline = new ArrayList<>(); + private ArrayList<MTEHatchOutputBeamline> mOutputBeamline = new ArrayList<>(); + + private static final int CASING_INDEX = GTUtility.getCasingTextureIndex(GregTechAPI.sBlockCasings5, 14); + + private static final byte MIN_GLASS_TIER = 6; + + /* + * g: Grate Machine Casing b: Borosilicate glass c: Shielded accelerator casing v: Vacuum k: Shielded glass d: + * Coolant Delivery casing y: Superconducting coil + */ + + static { + STRUCTURE_DEFINITION = StructureDefinition.<MTELINAC>builder() + .addShape( + STRUCTURE_PIECE_BASE, + new String[][] { { "ggggggg", "gbbbbbg", "gbbbbbg", "gbbibbg", "gbbbbbg", "gbbbbbg", "ggg~ggg" }, + { "ggggggg", "gcccccg", "gcccccg", "gcc-ccg", "gcccccg", "gcccccg", "ggggggg" }, + { "ccccccc", "cvvvvvc", "kvvvvvk", "kvv-vvk", "kvvvvvk", "cvvvvvc", "jcccccj" }, + { "cckkkcc", "cdddddc", "kdyyydk", "kdy-ydk", "kdyyydk", "cdddddc", "jcccccj" }, + { "cckkkcc", "cdvvvdc", "kvvvvvk", "kdv-vdk", "kvvvvvk", "cdvvvdc", "jcccccj" }, + { "cckkkcc", "cdddddc", "kdyyydk", "kdy-ydk", "kdyyydk", "cdddddc", "jcccccj" }, + { "cckkkcc", "cdvvvdc", "kvvvvvk", "kdv-vdk", "kvvvvvk", "cdvvvdc", "jcccccj" }, + { "cckhkcc", "cdddddc", "kdyyydk", "kdy-ydk", "kdyyydk", "cdddddc", "jcccccj" }, }) + .addShape( + STRUCTURE_PIECE_LAYER, + new String[][] { { "cckkkcc", "cdvvvdc", "kvvvvvk", "kdv-vdk", "kvvvvvk", "cdvvvdc", "ccccccc" }, + { "cckkkcc", "cdddddc", "kdyyydk", "kdy-ydk", "kdyyydk", "cdddddc", "ccccccc" } }) + .addShape( + STRUCTURE_PIECE_END, + new String[][] { { "cckkkcc", "cdvvvdc", "kvvvvvk", "kdv-vdk", "kvvvvvk", "cdvvvdc", "ccccccc" }, + { "cckhkcc", "cdddddc", "kdyyydk", "kdy-ydk", "kdyyydk", "cdddddc", "ccccccc" }, + { "cckkkcc", "cdvvvdc", "kvvvvvk", "kdv-vdk", "kvvvvvk", "cdvvvdc", "ccccccc" }, + { "cckkkcc", "cdddddc", "kdyyydk", "kdy-ydk", "kdyyydk", "cdddddc", "ccccccc" }, + { "cckkkcc", "cdvvvdc", "kvvvvvk", "kdv-vdk", "kvvvvvk", "cdvvvdc", "ccccccc" }, + { "cckkkcc", "cdddddc", "kdyyydk", "kdy-ydk", "kdyyydk", "cdddddc", "ccccccc" }, + { "ccccccc", "cvvvvvc", "kvvvvvk", "kvv-vvk", "kvvvvvk", "cvvvvvc", "ccccccc" }, + { "ccccccc", "ccccccc", "ccccccc", "ccc-ccc", "ccccccc", "ccccccc", "ccccccc" }, + { "ccccccc", "cbbbbbc", "cbbbbbc", "cbbobbc", "cbbbbbc", "cbbbbbc", "ccccccc" } }) + .addElement('c', ofBlock(LanthItemList.SHIELDED_ACCELERATOR_CASING, 0)) + .addElement('g', ofBlock(GregTechAPI.sBlockCasings3, 10)) // Grate Machine Casing + .addElement( + 'b', + BorosilicateGlass.ofBoroGlass( + (byte) 0, + MIN_GLASS_TIER, + Byte.MAX_VALUE, + (te, t) -> te.glassTier = t, + te -> te.glassTier)) + .addElement( + 'i', + buildHatchAdder(MTELINAC.class).hatchClass(MTEHatchInputBeamline.class) + .casingIndex(CASING_INDEX) + .dot(3) + .adder(MTELINAC::addBeamLineInputHatch) + .build()) + .addElement( + 'o', + buildHatchAdder(MTELINAC.class).hatchClass(MTEHatchOutputBeamline.class) + .casingIndex(CASING_INDEX) + .dot(4) + .adder(MTELINAC::addBeamLineOutputHatch) + .build()) + .addElement('v', ofBlock(LanthItemList.ELECTRODE_CASING, 0)) + .addElement('k', ofBlock(LanthItemList.SHIELDED_ACCELERATOR_GLASS, 0)) + .addElement('d', ofBlock(LanthItemList.COOLANT_DELIVERY_CASING, 0)) + .addElement('y', ofBlock(GregTechAPI.sBlockCasings1, 15)) // Superconducting coil + .addElement( + 'h', + buildHatchAdder(MTELINAC.class).atLeast(InputHatch, OutputHatch) + .casingIndex(CASING_INDEX) + .dot(2) + .build()) + + .addElement( + 'j', + buildHatchAdder(MTELINAC.class).atLeast(Maintenance, Energy) + .casingIndex(CASING_INDEX) + .dot(1) + .buildAndChain(ofBlock(LanthItemList.SHIELDED_ACCELERATOR_CASING, 0))) + + .build(); + } + + private float outputEnergy; + private int outputRate; + private int outputParticle; + private float outputFocus; + + private int length; + + public MTELINAC(int id, String name, String nameRegional) { + super(id, name, nameRegional); + } + + public MTELINAC(String name) { + super(name); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity te) { + return new MTELINAC(this.mName); + } + + @Override + protected MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Particle Accelerator") + .addInfo("Controller block for the LINAC") + .addInfo("Accelerates charged particles to higher energies") + .addInfo("Increasing length increases output energy, but decreases focus") + .addInfo("Use a lower temperature coolant to improve focus") + // .addInfo("Extendable, with a minimum length of 18 blocks") + .addInfo(DescTextLocalization.BLUEPRINT_INFO) + .addInfo(DescTextLocalization.BEAMLINE_SCANNER_INFO) + .addInfo("Valid Coolants:"); + + // Valid coolant list + for (String fluidName : BeamlineRecipeLoader.coolantMap.keySet()) { + + tt.addInfo( + "- " + FluidRegistry.getFluid(fluidName) + .getLocalizedName(null)); + + } + + tt.addInfo("Requires (length + 1)kL/s of coolant") + .addSeparator() + .beginVariableStructureBlock(7, 7, 7, 7, 19, 83, false) + .addController("Front bottom") + .addCasingInfoRange(LanthItemList.SHIELDED_ACCELERATOR_CASING.getLocalizedName(), 325, 1285, false) + .addCasingInfoRange(LanthItemList.COOLANT_DELIVERY_CASING.getLocalizedName(), 148, 852, false) + .addCasingInfoRange(LanthItemList.SHIELDED_ACCELERATOR_GLASS.getLocalizedName(), 127, 703, false) + .addCasingInfoRange("Superconducting Coil Block", 56, 312, false) + .addCasingInfoRange(LanthItemList.ELECTRODE_CASING.getLocalizedName(), 156, 732, false) + .addCasingInfoExactly("Grate Machine Casing", 47, false) + .addCasingInfoExactly("Borosilicate Glass (LuV+)", 48, false) + .addEnergyHatch(addDotText(1)) + .addMaintenanceHatch(addDotText(1)) + .addInputHatch(addDotText(2)) + .addOutputHatch(addDotText(2)) + .addOtherStructurePart("Beamline Input Hatch", addDotText(3)) + .addOtherStructurePart("Beamline Output Hatch", addDotText(4)) + + .toolTipFinisher("GTNH: Lanthanides");; + return tt; + } + + private boolean addBeamLineInputHatch(IGregTechTileEntity te, int casingIndex) { + + if (te == null) return false; + + IMetaTileEntity mte = te.getMetaTileEntity(); + + if (mte == null) return false; + + if (mte instanceof MTEHatchInputBeamline) { + return this.mInputBeamline.add((MTEHatchInputBeamline) mte); + } + + return false; + } + + private boolean addBeamLineOutputHatch(IGregTechTileEntity te, int casingIndex) { + + if (te == null) return false; + + IMetaTileEntity mte = te.getMetaTileEntity(); + + if (mte == null) return false; + + if (mte instanceof MTEHatchOutputBeamline) { + return this.mOutputBeamline.add((MTEHatchOutputBeamline) mte); + } + + return false; + } + + @Override + public boolean checkRecipe(ItemStack itemStack) { + + float tempFactor = 0; + // Focus as determined by multi properties + float machineFocus = 0; + // Input particle focus + float inputFocus = 0; + + // Output focus to be set + outputFocus = 0; + + float voltageFactor = 0; + float inputEnergy = 0; + + machineTemp = 0; + + // Energy quantity determined by multi + float machineEnergy = 0; + outputEnergy = 0; + + int particleId = 0; + outputParticle = 0; + + int inputRate = 0; + outputRate = 0; + + ArrayList<FluidStack> tFluidInputs = this.getStoredFluids(); + if (tFluidInputs.size() == 0) { + this.doRandomMaintenanceDamage(); // Penalise letting coolant run dry + this.stopMachine(SimpleShutDownReason.ofCritical("gtnhlanth.nocoolant")); + return false; + } + + // Coolant input + FluidStack primFluid = tFluidInputs.get(0); + + // 1b (1000L)/m/operation + final int fluidConsumed = 1000 * length; + + this.mEfficiency = (10000 - (this.getIdealStatus() - this.getRepairStatus()) * 1000); + this.mEfficiencyIncrease = 10000; + + if (this.getInputInformation() == null) { + return false; + } + + if (this.getInputInformation() + .getEnergy() == 0) { + return false; + } + + particleId = this.getInputInformation() + .getParticleId(); + Particle inputParticle = Particle.getParticleFromId(particleId); + + if (!inputParticle.canAccelerate()) { + stopMachine(SimpleShutDownReason.ofCritical("gtnhlanth.noaccel")); + return false; + } + + mMaxProgresstime = 1 * TickTime.SECOND; + // Consume the input tier's corresponding practical voltage instead of the maximum suggested by the logic + mEUt = (int) -GTValues.VP[(int) this.getInputVoltageTier()]; + + // Particle stays the same with this multiblock + outputParticle = particleId; + + if (primFluid.isFluidEqual(new FluidStack(FluidRegistry.getFluid("ic2coolant"), 1))) { + tempFactor = calculateTemperatureFactor(60); // Default temp of 300 is unreasonable + machineTemp = 60; // Solely for tricorder use + } else { + tempFactor = calculateTemperatureFactor( + primFluid.getFluid() + .getTemperature()); + machineTemp = primFluid.getFluid() + .getTemperature(); // Solely for tricorder use + } + + machineFocus = Math.max(((-0.9f) * this.length * tempFactor) + 110, 5); // Min of 5 + if (machineFocus > 90) { // Max of 90 + machineFocus = 90; + } + + inputFocus = this.getInputInformation() + .getFocus(); + + outputFocus = (inputFocus > machineFocus) ? ((inputFocus + machineFocus) / 2) + : inputFocus * (machineFocus / 100); // If input focus > machine focus, take the average of both, else + // weigh the former by the latter + + long voltage = this.getMaxInputVoltage(); + // voltageFactor = calculateVoltageFactor(voltage); + + // machineEnergy = Math.max(-((60) / this.length) * voltageFactor + 60_000, 2000); // Minimum of 2000keV + + machineEnergy = (float) Math.max(length / 4 * Math.pow(voltage, 1.0 / 3.0), 50); // Minimum of 50keV + + inputEnergy = this.getInputInformation() + .getEnergy(); + /* + * outputEnergy = Math.min( + * (1 + inputEnergy / Particle.getParticleFromId(outputParticle) + * .maxSourceEnergy()) * machineEnergy, + * 120_000); // TODO more complex calculation than just + * // addition + */ + + outputEnergy = (float) Math.pow( + 10, + 1 + inputEnergy / Particle.getParticleFromId(outputParticle) + .maxSourceEnergy()) + * machineEnergy; + + inputRate = this.getInputInformation() + .getRate(); + outputRate = inputRate; // Cannot increase rate with this multiblock + + if (Util.coolantFluidCheck(primFluid, fluidConsumed)) { + + this.stopMachine(SimpleShutDownReason.ofCritical("gtnhlanth.inscoolant")); + return false; + + } + + primFluid.amount -= fluidConsumed; + + Fluid fluidOutput = BeamlineRecipeLoader.coolantMap.get( + primFluid.getFluid() + .getName()); + + if (Objects.isNull(fluidOutput)) return false; + + FluidStack fluidOutputStack = new FluidStack(fluidOutput, fluidConsumed); + + if (Objects.isNull(fluidOutputStack)) return false; + + this.addFluidOutputs(new FluidStack[] { fluidOutputStack }); + + outputAfterRecipe(); + + return true; + } + + private void outputAfterRecipe() { + + if (!mOutputBeamline.isEmpty()) { + + BeamLinePacket packet = new BeamLinePacket( + new BeamInformation(outputEnergy, outputRate, outputParticle, outputFocus)); + + for (MTEHatchOutputBeamline o : mOutputBeamline) { + + o.q = packet; + } + } + } + + @Override + public void stopMachine() { + + // GTLog.out.print("Machine stopped"); + outputFocus = 0; + outputEnergy = 0; + outputParticle = 0; + outputRate = 0; + machineTemp = 0; + super.stopMachine(); + } + + @Override + public void stopMachine(ShutDownReason reason) { + + outputFocus = 0; + outputEnergy = 0; + outputParticle = 0; + outputRate = 0; + machineTemp = 0; + super.stopMachine(reason); + + } + + @Override + public String[] getInfoData() { + + long storedEnergy = 0; + long maxEnergy = 0; + for (MTEHatchEnergy tHatch : mEnergyHatches) { + if (tHatch.isValid()) { + storedEnergy += tHatch.getBaseMetaTileEntity() + .getStoredEU(); + maxEnergy += tHatch.getBaseMetaTileEntity() + .getEUCapacity(); + } + } + + BeamInformation information = this.getInputInformation(); + + return new String[] { + /* 1 */ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": " + + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(mProgresstime / 20) + + EnumChatFormatting.RESET + + " s / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(mMaxProgresstime / 20) + + EnumChatFormatting.RESET + + " s", + /* 2 */ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": " + + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(storedEnergy) + + EnumChatFormatting.RESET + + " EU / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(maxEnergy) + + EnumChatFormatting.RESET + + " EU", + /* 3 */ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": " + + EnumChatFormatting.RED + + GTUtility.formatNumbers(getActualEnergyUsage()) + + EnumChatFormatting.RESET + + " EU/t", + /* 4 */ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(getMaxInputVoltage()) + + EnumChatFormatting.RESET + + " EU/t(*2A) " + + StatCollector.translateToLocal("GT5U.machines.tier") + + ": " + + EnumChatFormatting.YELLOW + + VN[GTUtility.getTier(getMaxInputVoltage())] + + EnumChatFormatting.RESET, + /* 5 */ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": " + + EnumChatFormatting.RED + + (getIdealStatus() - getRepairStatus()) + + EnumChatFormatting.RESET + + " " + + StatCollector.translateToLocal("GT5U.multiblock.efficiency") + + ": " + + EnumChatFormatting.YELLOW + + Float.toString(mEfficiency / 100.0F) + + EnumChatFormatting.RESET + + " %", + + /* 7 */ EnumChatFormatting.BOLD + StatCollector.translateToLocal("beamline.info") + + ": " + + EnumChatFormatting.RESET, + + StatCollector.translateToLocal("beamline.temperature") + ": " // Temperature: + + EnumChatFormatting.DARK_RED + + machineTemp + + EnumChatFormatting.RESET + + " K", // e.g. "137 K" + + StatCollector.translateToLocal("beamline.coolusage") + ": " // Coolant usage: + + EnumChatFormatting.AQUA + + length + + EnumChatFormatting.RESET + + " kL/s", // e.g. "24 kL/s + + /* 8 */ EnumChatFormatting.BOLD + StatCollector.translateToLocal("beamline.in_pre") + + ": " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.particle") + ": " // "Multiblock Beamline Input:" + + EnumChatFormatting.GOLD + + Particle.getParticleFromId(information.getParticleId()) + .getLocalisedName() // e.g. "Electron + // (e-)" + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.energy") + ": " // "Energy:" + + EnumChatFormatting.DARK_RED + + information.getEnergy() + + EnumChatFormatting.RESET + + " keV", // e.g. "10240 keV" + StatCollector.translateToLocal("beamline.focus") + ": " // "Focus:" + + EnumChatFormatting.BLUE + + information.getFocus() + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.amount") + ": " // "Amount:" + + EnumChatFormatting.LIGHT_PURPLE + + information.getRate(), + EnumChatFormatting.BOLD + StatCollector.translateToLocal("beamline.out_pre") // "Multiblock Beamline + // Output:" + + ": " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.particle") + ": " + + EnumChatFormatting.GOLD + + Particle.getParticleFromId(this.outputParticle) + .getLocalisedName() + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.energy") + ": " + + EnumChatFormatting.DARK_RED + + this.outputEnergy + + EnumChatFormatting.RESET + + " keV", + StatCollector.translateToLocal( + "beamline.focus") + ": " + EnumChatFormatting.BLUE + this.outputFocus + " " + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.amount") + ": " + + EnumChatFormatting.LIGHT_PURPLE + + this.outputRate, }; + } + + private BeamInformation getInputInformation() { + + for (MTEHatchInputBeamline in : this.mInputBeamline) { // Easy way to find the desired input. Efficient? No. + // Will it matter? No :boubs_glasses: + + if (in.q == null) return new BeamInformation(0, 0, 0, 0); + // if (in.q == null) return new BeamInformation(10000, 10, 0, 90); // temporary for testing purposes + + return in.q.getContent(); + } + return null; + } + + private static float calculateTemperatureFactor(int fluidTemp) { + + float factor = (float) Math.pow(1.1, 0.2 * fluidTemp); + return factor; + } + + /* + * private static float calculateVoltageFactor(long voltage) { + * float factor = (float) Math.pow(1.00009, -(0.1 * voltage - 114000)); + * return factor; + * } + */ + + @Override + public String[] getStructureDescription(ItemStack arg0) { + return DescTextLocalization.addText("LINAC.hint", 11); + } + + @Override + public boolean checkMachine(IGregTechTileEntity mte, ItemStack stack) { + + mInputBeamline.clear(); + mOutputBeamline.clear(); + + this.outputEnergy = 0; + this.outputRate = 0; + this.outputParticle = 0; + this.outputFocus = 0; + + this.glassTier = 0; + + this.onEndInnerLayer = false; + + length = 8; // Base piece length + + if (!checkPiece(STRUCTURE_PIECE_BASE, 3, 6, 0)) return false; + + while (length < 128) { + + if (!checkPiece(STRUCTURE_PIECE_LAYER, 3, 6, -length)) { + if (!checkPiece(STRUCTURE_PIECE_END, 3, 6, -length)) { + return false; + } + break; + } ; + + length += 2; + } + + // if (!checkPiece(STRUCTURE_PIECE_END, 3, 6, -length)) return false; + + // Likely off by one or two, not visible to player however so doesn't particularly matter + length += 8; + + return this.mInputBeamline.size() == 1 && this.mOutputBeamline.size() == 1 + && this.mMaintenanceHatches.size() == 1 + && this.mEnergyHatches.size() <= 2 + && this.glassTier >= MIN_GLASS_TIER; + } + + @Override + public void construct(ItemStack stackSize, boolean hintsOnly) { + + buildPiece(STRUCTURE_PIECE_BASE, stackSize, hintsOnly, 3, 6, 0); + + int lLength = Math.max(stackSize.stackSize + 7, 8); // !! + + if (!(lLength % 2 == 0)) { + lLength++; // Otherwise you get gaps at the end + } + + for (int i = -8; i > -lLength - 1; i -= 2) { + + // GTLog.out.print("Building inner piece! i = " + i); + + buildPiece(STRUCTURE_PIECE_LAYER, stackSize, hintsOnly, 3, 6, i); + } + + buildPiece(STRUCTURE_PIECE_END, stackSize, hintsOnly, 3, 6, -(lLength + 2)); + + StructureLib.addClientSideChatMessages("Length: " + (11 + lLength) + " blocks."); + } + + @Override + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + + elementBudget = 200; // Maybe make a config + + if (mMachine) return -1; + + int build = 0; + + build = survivialBuildPiece(STRUCTURE_PIECE_BASE, stackSize, 3, 6, 0, elementBudget, env, false, true); + + if (build >= 0) return build; // Incomplete + + int lLength = Math.max(stackSize.stackSize + 7, 8); // !! + + if (!(lLength % 2 == 0)) { + lLength++; // Otherwise you get gaps at the end + } + + for (int i = -8; i > -lLength - 1; i -= 2) { + + build = survivialBuildPiece(STRUCTURE_PIECE_LAYER, stackSize, 3, 6, i, elementBudget, env, false, true); + + if (build >= 0) return build; + + } + + int finalOutput = survivialBuildPiece( + STRUCTURE_PIECE_END, + stackSize, + 3, + 6, + -(lLength + 2), + elementBudget, + env, + false, + true); + + return finalOutput; + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int aColorIndex, boolean active, boolean aRedstone) { + + // Placeholder + if (side == facing) { + if (active) return new ITexture[] { casingTexturePages[0][47], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW) + .extFacing() + .glow() + .build() }; + return new ITexture[] { casingTexturePages[0][47], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_GLOW) + .extFacing() + .glow() + .build() }; + } + return new ITexture[] { casingTexturePages[0][47] }; + } + + @Override + public IStructureDefinition<MTELINAC> getStructureDefinition() { + return STRUCTURE_DEFINITION; + } + + public boolean addInputHatchToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) { + this.onEndInnerLayer = true; + return super.addInputHatchToMachineList(aTileEntity, aBaseCasingIndex); + } + + @Override + public boolean isCorrectMachinePart(ItemStack aStack) { + return true; + } + + @Override + public int getMaxEfficiency(ItemStack aStack) { + return 10000; + } + + @Override + public int getDamageToComponent(ItemStack aStack) { + return 0; + } + + @Override + public boolean explodesOnComponentBreak(ItemStack aStack) { + return false; + } +} diff --git a/src/main/java/gtnhlanth/common/tileentity/MTESourceChamber.java b/src/main/java/gtnhlanth/common/tileentity/MTESourceChamber.java new file mode 100644 index 0000000000..68cc750005 --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/MTESourceChamber.java @@ -0,0 +1,409 @@ +package gtnhlanth.common.tileentity; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static gregtech.api.enums.GTValues.VN; +import static gregtech.api.enums.HatchElement.Energy; +import static gregtech.api.enums.HatchElement.InputBus; +import static gregtech.api.enums.HatchElement.Maintenance; +import static gregtech.api.enums.HatchElement.OutputBus; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages; +import static gregtech.api.util.GTStructureUtility.buildHatchAdder; +import static gtnhlanth.util.DescTextLocalization.BLUEPRINT_INFO; +import static gtnhlanth.util.DescTextLocalization.addDotText; + +import java.util.ArrayList; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidStack; + +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; + +import gregtech.api.GregTechAPI; +import gregtech.api.enums.GTValues; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.metatileentity.implementations.MTEEnhancedMultiBlockBase; +import gregtech.api.metatileentity.implementations.MTEHatchEnergy; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTUtility; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.api.util.shutdown.SimpleShutDownReason; +import gtnhlanth.common.beamline.BeamInformation; +import gtnhlanth.common.beamline.BeamLinePacket; +import gtnhlanth.common.beamline.Particle; +import gtnhlanth.common.hatch.MTEHatchOutputBeamline; +import gtnhlanth.common.register.LanthItemList; +import gtnhlanth.common.tileentity.recipe.beamline.BeamlineRecipeAdder2; +import gtnhlanth.common.tileentity.recipe.beamline.RecipeSC; +import gtnhlanth.util.DescTextLocalization; + +public class MTESourceChamber extends MTEEnhancedMultiBlockBase<MTESourceChamber> implements ISurvivalConstructable { + + private static final IStructureDefinition<MTESourceChamber> STRUCTURE_DEFINITION; + + private ArrayList<MTEHatchOutputBeamline> mOutputBeamline = new ArrayList<>(); + + private static final int CASING_INDEX = GTUtility.getCasingTextureIndex(GregTechAPI.sBlockCasings5, 14); + + private float outputEnergy; + private int outputRate; + private int outputParticle; + private float outputFocus; + + static { + STRUCTURE_DEFINITION = StructureDefinition.<MTESourceChamber>builder() + .addShape( + "sc", + new String[][] { { "ccccc", "ckkkc", "ckikc", "ckkkc", "dd~dd" }, + { "ckkkc", "keeek", "ke-ek", "keeek", "ccocc" }, { "ckkkc", "k---k", "k---k", "k---k", "ccccc" }, + { "ckkkc", "k---k", "k---k", "k---k", "ccccc" }, { "ckkkc", "keeek", "ke-ek", "keeek", "ccccc" }, + { "ccccc", "ckkkc", "ckbkc", "ckkkc", "ccccc" } }) + .addElement('c', ofBlock(LanthItemList.SHIELDED_ACCELERATOR_CASING, 0)) + .addElement('k', ofBlock(LanthItemList.SHIELDED_ACCELERATOR_GLASS, 0)) + .addElement('e', ofBlock(LanthItemList.ELECTRODE_CASING, 0)) + .addElement( + 'b', + buildHatchAdder(MTESourceChamber.class).hatchClass(MTEHatchOutputBeamline.class) + .casingIndex(CASING_INDEX) + .dot(4) + .adder(MTESourceChamber::addBeamLineOutputHatch) + .build()) + .addElement( + 'i', + buildHatchAdder(MTESourceChamber.class).atLeast(InputBus) + .casingIndex(CASING_INDEX) + .dot(1) + .build()) + .addElement( + 'o', + buildHatchAdder(MTESourceChamber.class).atLeast(OutputBus) + .casingIndex(CASING_INDEX) + .dot(2) + .build()) + .addElement( + 'd', + buildHatchAdder(MTESourceChamber.class).atLeast(Maintenance, Energy) + .casingIndex(CASING_INDEX) + .dot(3) + .buildAndChain(ofBlock(LanthItemList.SHIELDED_ACCELERATOR_CASING, 0))) + + .build(); + } + + public MTESourceChamber(int id, String name, String nameRegional) { + super(id, name, nameRegional); + } + + public MTESourceChamber(String name) { + super(name); + } + + @Override + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + if (mMachine) return -1; + return survivialBuildPiece("sc", stackSize, 2, 4, 0, elementBudget, env, false, true); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity te) { + return new MTESourceChamber(this.mName); + } + + @Override + protected MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Particle Source") + .addInfo("Controller block for the Source Chamber") + .addInfo(BLUEPRINT_INFO) + .addInfo(DescTextLocalization.BEAMLINE_SCANNER_INFO) + .addSeparator() + .beginStructureBlock(5, 5, 6, true) + .addController("Front bottom") + .addCasingInfoExactly(LanthItemList.SHIELDED_ACCELERATOR_CASING.getLocalizedName(), 56, false) + .addCasingInfoExactly(LanthItemList.SHIELDED_ACCELERATOR_GLASS.getLocalizedName(), 52, false) + .addCasingInfoExactly(LanthItemList.ELECTRODE_CASING.getLocalizedName(), 16, false) + .addOtherStructurePart("Beamline Output Hatch", addDotText(4)) + .addEnergyHatch(addDotText(3)) + .addMaintenanceHatch(addDotText(3)) + .addInputBus(addDotText(1)) + .addOutputBus(addDotText(2)) + .toolTipFinisher("GTNH: Lanthanides"); + return tt; + } + + private boolean addBeamLineOutputHatch(IGregTechTileEntity te, int casingIndex) { + + if (te == null) return false; + + IMetaTileEntity mte = te.getMetaTileEntity(); + + if (mte == null) return false; + + if (mte instanceof MTEHatchOutputBeamline) { + return this.mOutputBeamline.add((MTEHatchOutputBeamline) mte); + } + + return false; + } + /* + * protected OverclockDescriber createOverclockDescriber() { return new EUNoTotalOverclockDescriber((byte) 4, 1); } + */ + + @Override + public boolean checkRecipe(ItemStack itemStack) { + + // GTLog.out.print("In checkRecipe"); + + // No input particle, so no input quantities + + outputFocus = 0; + outputEnergy = 0; + outputParticle = 0; + outputRate = 0; + + ItemStack[] tItems = this.getStoredInputs() + .toArray(new ItemStack[0]); + // GTLog.out.print(Arrays.toString(tItems)); + long tVoltageMaxTier = this.getMaxInputVoltage(); // Used to keep old math the same + long tVoltageActual = GTValues.VP[(int) this.getInputVoltageTier()]; + + RecipeSC tRecipe = (RecipeSC) BeamlineRecipeAdder2.instance.SourceChamberRecipes + .findRecipe(this.getBaseMetaTileEntity(), false, tVoltageActual, new FluidStack[] {}, tItems); + + if (tRecipe == null || !tRecipe.isRecipeInputEqual(true, new FluidStack[] {}, tItems)) return false; // Consumes + // input + // item + + this.mEfficiency = (10000 - (this.getIdealStatus() - this.getRepairStatus()) * 1000); + this.mEfficiencyIncrease = 10000; + + this.mMaxProgresstime = tRecipe.mDuration; + if (mMaxProgresstime == Integer.MAX_VALUE - 1 && this.mEUt == Integer.MAX_VALUE - 1) return false; + + mEUt = (int) -tVoltageActual; + if (this.mEUt > 0) this.mEUt = (-this.mEUt); + + outputParticle = tRecipe.particleId; + float maxParticleEnergy = Particle.getParticleFromId(outputParticle) + .maxSourceEnergy(); // The maximum energy a + // particle can possess + // when produced by this + // multiblock + float maxMaterialEnergy = tRecipe.maxEnergy; // The maximum energy for the recipe processed + outputEnergy = (float) Math.min( + (-maxMaterialEnergy) * Math.pow(1.001, -(tRecipe.energyRatio) * (tVoltageMaxTier - tRecipe.mEUt)) + + maxMaterialEnergy, + maxParticleEnergy); + + if (outputEnergy <= 0) { + stopMachine(SimpleShutDownReason.ofCritical("gtnhlanth.scerror")); + return false; + } + + outputFocus = tRecipe.focus; + outputRate = tRecipe.rate; + + this.mOutputItems = tRecipe.mOutputs; + this.updateSlots(); + + outputAfterRecipe(); + + return true; + } + + @Override + public String[] getStructureDescription(ItemStack arg0) { + return DescTextLocalization.addText("SourceChamber.hint", 7); // Generate 7 localised hint strings in structure + // description + } + + private void outputAfterRecipe() { + + if (!mOutputBeamline.isEmpty()) { + + BeamLinePacket packet = new BeamLinePacket( + new BeamInformation(outputEnergy, outputRate, outputParticle, outputFocus)); + + for (MTEHatchOutputBeamline o : mOutputBeamline) { + + o.q = packet; + } + } + } + + @Override + public void stopMachine() { + outputFocus = 0; + outputEnergy = 0; + outputParticle = 0; + outputRate = 0; + super.stopMachine(); + } + + @Override + public RecipeMap<?> getRecipeMap() { + return BeamlineRecipeAdder2.instance.SourceChamberRecipes; + } + + @Override + public String[] getInfoData() { + + long storedEnergy = 0; + long maxEnergy = 0; + for (MTEHatchEnergy tHatch : mEnergyHatches) { + if (tHatch.isValid()) { + storedEnergy += tHatch.getBaseMetaTileEntity() + .getStoredEU(); + maxEnergy += tHatch.getBaseMetaTileEntity() + .getEUCapacity(); + } + } + + return new String[] { + /* 1 */ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": " + + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(mProgresstime / 20) + + EnumChatFormatting.RESET + + " s / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(mMaxProgresstime / 20) + + EnumChatFormatting.RESET + + " s", + /* 2 */ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": " + + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(storedEnergy) + + EnumChatFormatting.RESET + + " EU / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(maxEnergy) + + EnumChatFormatting.RESET + + " EU", + /* 3 */ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": " + + EnumChatFormatting.RED + + GTUtility.formatNumbers(getActualEnergyUsage()) + + EnumChatFormatting.RESET + + " EU/t", + /* 4 */ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(getMaxInputVoltage()) + + EnumChatFormatting.RESET + + " EU/t(*2A) " + + StatCollector.translateToLocal("GT5U.machines.tier") + + ": " + + EnumChatFormatting.YELLOW + + VN[GTUtility.getTier(getMaxInputVoltage())] + + EnumChatFormatting.RESET, + /* 5 */ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": " + + EnumChatFormatting.RED + + (getIdealStatus() - getRepairStatus()) + + EnumChatFormatting.RESET + + " " + + StatCollector.translateToLocal("GT5U.multiblock.efficiency") + + ": " + + EnumChatFormatting.YELLOW + + Float.toString(mEfficiency / 100.0F) + + EnumChatFormatting.RESET + + " %", + EnumChatFormatting.BOLD + StatCollector.translateToLocal("beamline.out_pre") + + ": " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.particle") + ": " + + EnumChatFormatting.GOLD + + Particle.getParticleFromId(this.outputParticle) + .getLocalisedName() + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.energy") + ": " + + EnumChatFormatting.DARK_RED + + this.outputEnergy + + EnumChatFormatting.RESET + + " keV", + StatCollector.translateToLocal( + "beamline.focus") + ": " + EnumChatFormatting.BLUE + this.outputFocus + " " + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.amount") + ": " + + EnumChatFormatting.LIGHT_PURPLE + + this.outputRate, }; + } + + @Override + public void construct(ItemStack stackSize, boolean hintsOnly) { + buildPiece("sc", stackSize, hintsOnly, 2, 4, 0); + } + + @Override + public IStructureDefinition<MTESourceChamber> getStructureDefinition() { + return STRUCTURE_DEFINITION; + } + + @Override + public boolean isCorrectMachinePart(ItemStack aStack) { + return true; + } + + @Override + public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { + + this.mOutputBeamline.clear(); // Necessary due to the nature of the beamline hatch adder + + return checkPiece("sc", 2, 4, 0) && this.mMaintenanceHatches.size() == 1 + && this.mInputBusses.size() == 1 + && this.mOutputBusses.size() == 1 + && this.mOutputBeamline.size() == 1 + && this.mEnergyHatches.size() == 1; + } + + @Override + public int getMaxEfficiency(ItemStack aStack) { + return 10000; + } + + @Override + public int getDamageToComponent(ItemStack aStack) { + return 0; + } + + @Override + public boolean explodesOnComponentBreak(ItemStack aStack) { + return false; + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int colorIndex, boolean active, boolean redstoneLevel) { + + // Placeholder + if (side == facing) { + if (active) return new ITexture[] { casingTexturePages[1][14], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW) + .extFacing() + .glow() + .build() }; + return new ITexture[] { casingTexturePages[1][14], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_GLOW) + .extFacing() + .glow() + .build() }; + } + return new ITexture[] { casingTexturePages[1][14] }; + } +} diff --git a/src/main/java/gtnhlanth/common/tileentity/MTESynchrotron.java b/src/main/java/gtnhlanth/common/tileentity/MTESynchrotron.java new file mode 100644 index 0000000000..3b67f8e172 --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/MTESynchrotron.java @@ -0,0 +1,1077 @@ +package gtnhlanth.common.tileentity; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlockAdder; +import static gregtech.api.enums.GTValues.VN; +import static gregtech.api.enums.HatchElement.Energy; +import static gregtech.api.enums.HatchElement.InputHatch; +import static gregtech.api.enums.HatchElement.Maintenance; +import static gregtech.api.enums.HatchElement.OutputHatch; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages; +import static gregtech.api.util.GTStructureUtility.buildHatchAdder; +import static gtnhlanth.util.DescTextLocalization.addDotText; + +import java.util.ArrayList; +import java.util.Objects; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; + +import com.google.common.collect.ImmutableMap; +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; + +import bartworks.API.BorosilicateGlass; +import gregtech.api.GregTechAPI; +import gregtech.api.enums.GTValues; +import gregtech.api.enums.TickTime; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.metatileentity.implementations.MTEEnhancedMultiBlockBase; +import gregtech.api.metatileentity.implementations.MTEHatchEnergy; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTUtility; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.api.util.shutdown.ShutDownReason; +import gregtech.api.util.shutdown.SimpleShutDownReason; +import gtnhlanth.common.beamline.BeamInformation; +import gtnhlanth.common.beamline.BeamLinePacket; +import gtnhlanth.common.beamline.Particle; +import gtnhlanth.common.block.BlockAntennaCasing; +import gtnhlanth.common.hatch.MTEHatchInputBeamline; +import gtnhlanth.common.hatch.MTEHatchOutputBeamline; +import gtnhlanth.common.register.LanthItemList; +import gtnhlanth.common.tileentity.recipe.beamline.BeamlineRecipeLoader; +import gtnhlanth.util.DescTextLocalization; +import gtnhlanth.util.Util; + +public class MTESynchrotron extends MTEEnhancedMultiBlockBase<MTESynchrotron> implements ISurvivalConstructable { + + private static final IStructureDefinition<MTESynchrotron> STRUCTURE_DEFINITION; + + protected static final String STRUCTURE_PIECE_ENTRANCE = "entrance"; + protected static final String STRUCTURE_PIECE_BASE = "base"; + + public static final int CONSUMED_FLUID = 32_000; // Fluid consumed per processed recipe, maybe increase with EU + public static final int MIN_INPUT_FOCUS = 25; // Inclusive + + private ArrayList<MTEHatchInputBeamline> mInputBeamline = new ArrayList<>(); + private ArrayList<MTEHatchOutputBeamline> mOutputBeamline = new ArrayList<>(); + + public ArrayList<BlockAntennaCasing> mAntennaCasings = new ArrayList<>(); + + private static final int CASING_INDEX = GTUtility.getCasingTextureIndex(GregTechAPI.sBlockCasings5, 14); + + private static final byte MIN_GLASS_TIER = 6; + + private int energyHatchTier; + + private int antennaeTier; + + private Byte glassTier; + + /* + * c: Shielded accelerator casing v: Vacuum k: Superconducting coil d: Coolant Delivery casing + */ + + // TODO: E > 1200eV for x-ray lithography + // spotless:off + static { + + STRUCTURE_DEFINITION = StructureDefinition.<MTESynchrotron>builder().addShape( + STRUCTURE_PIECE_ENTRANCE, + + + + new String[][] { + { + " ", + " ccc ", + " cgggc ", + " cgvgc ", + " cgggc ", + " ccc " + } + }) + .addShape( + STRUCTURE_PIECE_BASE, + + new String[][] { + { + " ", + " ccc ", + " ccccc cjjjjjc ", + " cc-cc cjjc~cjjc ", + " ccccc cjjjjjc ", + " ccc ", + " " + }, + { + " ", + " ccc ccccccccccc ", + " c---c ccc-------ccc ", + " c---c ccc-------ccc ", + " c---c ccc-------ccc ", + " ccc ccccccccccc ", + " " + }, + { + " ccccccccccc ", + " ccc cc-----------cc ", + " c---c cc-------------cc ", + " c---c cc-------------cc ", + " c---c cc-------------cc ", + " ccc ccc---------ccc ", + " ccccccccccc " + }, + { + " ccccccccccccccc ", + " ccc cc---------------cc ", + " c---ccc-----------------c ", + " c---ccc-----------------cc ", + " c---ccc-----------------c ", + " ccc cc---------------cc ", + " ccccccccccccccc ", + + }, + { + " ccc ccccccccccccccccc ", + " ckkkccc-----------------cc ", + "ck---kc-------------------cc ", + "ck---kc--------------------c ", + "ck---kc-------------------cc ", + " ckkkccc-----------------cc ", + " ccc cccccccccccccccccc " + + }, + { + " cccccccccccc ccccccc ", + " cdddcc-------ccccc-------cc ", + "cd---d----------------------c ", + "cd---d----------------------c ", + "cd---d----------------------c ", + " cdddcc-------ccccc-------cc ", + " cccccccccccc ccccccc ", + }, + { + " ccccccccc ccccc ", + " ckkkc-----cccc cccc-----cc ", + "ck---k-------ccccccc--------c ", + "ck---k-------ccccccc---------c ", + "ck---k-------ccccccc--------c ", + " ckkkc-----cccc cccc-----cc ", + " ccccccccc ccccc " + }, + { + " cccccccc ccccc ", + " c--------cc cc-----cc ", + "c----------cc cc-------c ", + "c----------cc cc-------c ", + "c----------cc cc-------c ", + " c--------cc cc-----cc ", + " cccccccc ccccc " + + }, + { + " ccccccc ccccc ", + " c-------c c-----c ", + "c---------c c-------c ", + "c---------c c-------c ", + "c---------c c-------c ", + " c-------c c-----c ", + " ccccccc ccccc " + + }, + { + " cccccc ccccc ", + " c------c c-----c ", + "c--------c c------c ", + "c--------c c------c ", + "c--------c c------c ", + " c------c c-----c ", + " cccccc ccccc " + + }, + { + " ccccc cccc ", + " c-----c c----c ", + "c-------c c------c ", + "c-------c c------c ", + "c-------c c------c ", + " c-----c c----c ", + " ccccc cccc " + + }, + { + " cccc ccc ", + " c----cc cc---cc ", + "c------c c-----c ", + "c------c c-----c ", + "c------c c-----c ", + " c----cc cc---cc ", + " cccc ccc " + + }, + { + " cccc cccc ", + " c---cc c----c ", + "c------c c-----c ", + "c------c c-----cc ", + "c------c c-----c ", + " c---cc cc---c ", + " cccc cccc " + + }, + { + " cccc cccc ", + " c---cc c----c ", + "c-----c c----cc ", + "c-----c c----cc ", + "c-----c c----cc ", + " c---cc cc---c ", + " cccc cccc " + + }, + { + " ccc ccc ", + " ckkkcc cckkkc ", + "ck---kc ck---kc ", + "ck---kc ck---kc ", + "ck---kc ck---kc ", + " ckkkcc cckkkc ", + " ccc ccc " + + }, + { + " cec cec ", + " cnanc cnanc ", + "cn---nc cn---nc ", + "cn---nc cn---nc ", + "cn---nc cn---nc ", + " cnnnc cnnnc ", + " ccc ccc " + + }, + { + " cic cic ", + " cndnc cndnc ", + "cn---nc cn---nc ", + "cn---nc cn---nc ", + "cn---nc cn---nc ", + " cndnc cndnc ", + " coc coc " + + }, + { + " cec cec ", + " cnanc cnanc ", + "cn---nc cn---nc ", + "cn---nc cn---nc ", + "cn---nc cn---nc ", + " cnnnc cnnnc ", + " ccc ccc " + + }, + { + " ccc ccc ", + " ckkkcc cckkkc ", + "ck---kc ck---kc ", + "ck---kc ck---kc ", + "ck---kc ck---kc ", + " ckkkcc cckkkc ", + " ccc ccc " + + }, + { + " cccc cccc ", + " c----c c----c ", + "cc----c c----cc ", + "cc----c c----cc ", + "cc----c c----cc ", + " c---cc cc---c ", + " cccc cccc " + + }, + { + " cccc cccc ", + " c----c c----c ", + " c-----c c-----c ", + "cc-----c c-----cc ", + " c-----c c-----c ", + " c---cc cc---c ", + " cccc cccc " + + }, + { + " ccc ccc ", + " cc---cc cc---cc ", + " c-----c c-----c ", + " c-----c c-----c ", + " c-----c c-----c ", + " cc---cc cc---cc ", + " ccc ccc " + + }, + { + " cccc cccc ", + " c----c c----c ", + " c------c c------c ", + " c------c c------c ", + " c------c c------c ", + " c----c c----c ", + " cccc cccc " + + }, + { + " ccccc ccccc ", + " c-----c c-----c ", + " c------c c------c ", + " c------c c------c ", + " c------c c------c ", + " c-----c c-----c ", + " ccccc ccccc " + + }, + { + " ccccc ccccc ", + " c-----c c-----c ", + " c-------c c-------c ", + " c-------c c-------c ", + " c-------c c-------c ", + " c-----c c-----c ", + " ccccc ccccc " + + }, + { + " ccccc ccccc ", + " c-----cc cc-----c ", + " c-------cc cc-------cc ", + " c-------cc cc-------cc ", + " c-------cc cc-------cc ", + " c-----cc cc------c ", + " ccccc cccccc " + + }, + { + " ccccc ccccccc ", + " cc-----cccc cccc-----ccc ", + " c--------ccccccc--------cccc ", + " c--------ccccccc--------cccc ", + " c--------ccccccc--------cccc ", + " cc-----cccc cccc------cc ", + " ccccc cccccc " + + }, + { + " ccccccc cccccccccc ", + " cc-------ccccc--------cccc ", + " c---------kdkdk--------ccccccccc", + " c---------kdkdk--------ccccccccc", + " c---------kdkdk--------ccccccccc", + " cc-------ccccc--------cccc ", + " ccccccc cccccccc " + + }, + { + " cccccccccccccccccccc ", + " cc-------------------ccccccccc", + " cc---------------------------cg", + " c----------------------------cg", + " cc---------------------------cg", + " c-------------------ccccccccc", + " ccccccccccccccccccc " + + }, + { + " ccccccccccccccccccc ", + " cc-----------------cccccccccc", + " c--------------------------cg", + " cc---------------------------b", + " c--------------------------cg", + " c-----------------cccccccccc", + " ccccccccccccccccc " + + }, + { + " ccccccccccccccc ", + " ccc-------------ccccccccccc", + " cc------------------------cg", + " cc------------------------cg", + " cc------------------------cg", + " ccc-------------ccccccccccc", + " ccccccccccccc " + + }, + { + " ", + " cccccccccccccccccc ", + " ccc-kdkdk------ccccccccccc", + " cc--kdkdk------ccccccccccc", + " ccc-kdkdk------ccccccccccc", + " cccccccccccccccccc " + + }, + { + " ", + " ", + " cccccccccccccccc ", + " ccccccccccccccccc ", + " cccccccccccccccc ", + " ", + " " + + } + + } + + ).addElement('c', ofBlock(LanthItemList.SHIELDED_ACCELERATOR_CASING, 0)) + .addElement('k', ofBlock(GregTechAPI.sBlockCasings1, 15)) // Superconducting coils + .addElement('d', ofBlock(LanthItemList.COOLANT_DELIVERY_CASING, 0)) + .addElement('e', buildHatchAdder(MTESynchrotron.class).atLeast(ImmutableMap.of(Energy, 4)).dot(6).casingIndex(CASING_INDEX).build()) + .addElement('n', ofBlock(LanthItemList.NIOBIUM_CAVITY_CASING, 0)) + .addElement('a', ofBlockAdder(MTESynchrotron::addAntenna, LanthItemList.ANTENNA_CASING_T1, 0)) //Antenna Casings + .addElement('i', buildHatchAdder(MTESynchrotron.class).atLeast(ImmutableMap.of(InputHatch, 2)).dot(4).casingIndex(CASING_INDEX).build()) + .addElement('o', buildHatchAdder(MTESynchrotron.class).atLeast(ImmutableMap.of(OutputHatch, 2)).dot(5).casingIndex(CASING_INDEX).build()) + .addElement('v', buildHatchAdder(MTESynchrotron.class).hatchClass(MTEHatchInputBeamline.class).casingIndex(CASING_INDEX) + .dot(1).adder(MTESynchrotron::addBeamlineInputHatch).build()) + .addElement('b', buildHatchAdder(MTESynchrotron.class).hatchClass(MTEHatchOutputBeamline.class).casingIndex(CASING_INDEX) + .dot(2).adder(MTESynchrotron::addBeamlineOutputHatch).build()) + .addElement('g', BorosilicateGlass.ofBoroGlass((byte) 0, MIN_GLASS_TIER, Byte.MAX_VALUE, (te, t) -> te.glassTier = t, te -> te.glassTier)) + .addElement('j', + buildHatchAdder(MTESynchrotron.class).atLeast(Maintenance).dot(3).casingIndex(CASING_INDEX) + .buildAndChain(LanthItemList.SHIELDED_ACCELERATOR_CASING, 0)) + + .build(); + + + + } + + // spotless:on + + /* + * v = pi * lorentz^2 * sfreq sfreq = sw / 2pi sw = e * B / mass(e) * c v = (e * B * l^2) / (2 * mass(e) * c) = + * 292.718624222 * l^2 * B + */ + + private float outputEnergy; + private int outputRate; + private int outputParticle; + private float outputFocus; + private float machineFocus; + + private int machineTemp; + + public MTESynchrotron(String aName) { + super(aName); + } + + public MTESynchrotron(int id, String name, String nameRegional) { + super(id, name, nameRegional); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new MTESynchrotron(this.mName); + } + + @Override + protected MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Particle Accelerator") + .addInfo("Controller block for the Synchrotron") + .addInfo("Torus-shaped, accelerates electrons to produce high-energy electromagnetic radiation") + .addInfo(DescTextLocalization.BLUEPRINT_INFO) + .addInfo(DescTextLocalization.BEAMLINE_SCANNER_INFO) + .addInfo("Valid Coolants:"); + + // Valid coolant list + for (String fluidName : BeamlineRecipeLoader.coolantMap.keySet()) { + + tt.addInfo( + "- " + FluidRegistry.getFluid(fluidName) + .getLocalizedName(null)); + + } + + tt.addInfo("Requires 32 kL/s of coolant") + .addSeparator() + .beginStructureBlock(36, 7, 34, true) + .addController("Front middle") + .addCasingInfoExactly(LanthItemList.SHIELDED_ACCELERATOR_CASING.getLocalizedName(), 676, false) + .addCasingInfoExactly("Superconducting Coil Block", 90, false) + .addCasingInfoExactly("Niobium Cavity Casing", 64, false) + .addCasingInfoExactly(LanthItemList.COOLANT_DELIVERY_CASING.getLocalizedName(), 28, false) + .addCasingInfoExactly("Borosilicate Glass Block (LuV+)", 16, false) + .addCasingInfoExactly("Antenna Casing (must match)", 4, true) + .addOtherStructurePart("Beamline Input Hatch", addDotText(1)) + .addOtherStructurePart("Beamline Output Hatch", addDotText(2)) + .addMaintenanceHatch(addDotText(3)) + .addInputHatch(addDotText(4)) + .addOutputHatch(addDotText(5)) + .addEnergyHatch(addDotText(6)) + + .toolTipFinisher("GTNH: Lanthanides"); + return tt; + } + + private boolean addBeamlineInputHatch(IGregTechTileEntity te, int casingIndex) { + + if (te == null) return false; + + IMetaTileEntity mte = te.getMetaTileEntity(); + + if (mte == null) return false; + + if (mte instanceof MTEHatchInputBeamline) { + return this.mInputBeamline.add((MTEHatchInputBeamline) mte); + } + + return false; + + } + + private boolean addBeamlineOutputHatch(IGregTechTileEntity te, int casingIndex) { + + if (te == null) return false; + + IMetaTileEntity mte = te.getMetaTileEntity(); + + if (mte == null) return false; + + if (mte instanceof MTEHatchOutputBeamline) { + return this.mOutputBeamline.add((MTEHatchOutputBeamline) mte); + } + + return false; + + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int aColorIndex, boolean active, boolean aRedstone) { + // Placeholder + if (side == facing) { + if (active) return new ITexture[] { casingTexturePages[1][14], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW) + .extFacing() + .glow() + .build() }; + return new ITexture[] { casingTexturePages[1][14], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_GLOW) + .extFacing() + .glow() + .build() }; + } + return new ITexture[] { casingTexturePages[1][14] }; + } + + @Override + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + elementBudget = 200; + + if (mMachine) return -1; + + int build = survivialBuildPiece(STRUCTURE_PIECE_ENTRANCE, stackSize, 16, 3, 1, elementBudget, env, false, true); + + if (build >= 0) return build; + + return survivialBuildPiece(STRUCTURE_PIECE_BASE, stackSize, 16, 3, 0, elementBudget, env, false, true); + + } + + @Override + public void construct(ItemStack stackSize, boolean hintsOnly) { + buildPiece(STRUCTURE_PIECE_ENTRANCE, stackSize, hintsOnly, 16, 3, 1); + buildPiece(STRUCTURE_PIECE_BASE, stackSize, hintsOnly, 16, 3, 0); + + } + + @Override + public IStructureDefinition<MTESynchrotron> getStructureDefinition() { + return STRUCTURE_DEFINITION; + } + + public boolean addEnergyInputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) { + if (aTileEntity == null) { + return false; + } + IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity(); + if (aMetaTileEntity == null) return false; + if (aMetaTileEntity instanceof MTEHatchEnergy) { + + MTEHatchEnergy hatch = (MTEHatchEnergy) aMetaTileEntity; + + // First energy hatch added + if (this.mEnergyHatches.size() == 0) this.energyHatchTier = hatch.mTier; + + // Disallow any hatches that don't match the tier of the first hatch added + if (hatch.mTier != this.energyHatchTier) return false; + + hatch.updateTexture(aBaseCasingIndex); + hatch.updateCraftingIcon(this.getMachineCraftingIcon()); + return mEnergyHatches.add(hatch); + } + return false; + } + + private boolean addAntenna(Block block, int meta) { + + if (block == null) return false; + + if (!(block instanceof BlockAntennaCasing)) return false; + + BlockAntennaCasing antennaBlock = (BlockAntennaCasing) block; + + int antennaTier = antennaBlock.getTier(); + + // First antenna casing added + if (this.mAntennaCasings.size() == 0) this.antennaeTier = antennaTier; + + if (antennaTier != this.antennaeTier) return false; + + return mAntennaCasings.add(antennaBlock); + + } + + @Override + public boolean isCorrectMachinePart(ItemStack aStack) { + return true; + } + + @Override + public boolean checkRecipe(ItemStack aStack) { + + float inputEnergy = 0; + float inputFocus = 0; + float inputRate = 0; + int inputParticleId = 0; + + machineFocus = 0; + machineTemp = 0; + + outputEnergy = 0; + outputFocus = 0; + outputRate = 0; + outputParticle = 0; + + float tempFactor = 0; + + float voltageFactor = 0; + + ArrayList<FluidStack> fluidList = this.getStoredFluids(); + + if (fluidList.size() == 0) { + + this.stopMachine(SimpleShutDownReason.ofCritical("gtnhlanth.nocoolant")); + + return false; + } + + this.mEfficiency = (10000 - (this.getIdealStatus() - this.getRepairStatus()) * 1000); + this.mEfficiencyIncrease = 10000; + + if (this.getInputInformation() == null) { + return false; + } + + if (this.getInputInformation() + .getEnergy() == 0) { // Only really applies if there's no input + return false; + } + + if (this.getInputInformation() + .getFocus() < MIN_INPUT_FOCUS) { + return false; + } + + inputParticleId = this.getInputInformation() + .getParticleId(); + + Particle inputParticle = Particle.getParticleFromId(inputParticleId); + + if (!inputParticle.canAccelerate()) { + stopMachine(SimpleShutDownReason.ofCritical("gtnhlanth.noaccel")); + return false; + } + + mMaxProgresstime = TickTime.SECOND; + + long voltage = this.getMaxInputVoltage(); + mEUt = (int) (-voltage / GTValues.V[(int) this.getInputVoltageTier()] + * GTValues.VP[(int) this.getInputVoltageTier()]); // Multiply VP by amps + + outputParticle = 1; // Photon + + FluidStack primaryFluid = fluidList.get(0); + + int fluidTemperature; + + if (primaryFluid.isFluidEqual(new FluidStack(FluidRegistry.getFluid("ic2coolant"), 1))) { + fluidTemperature = 60; // Default temp of 300 is unreasonable + } else { + fluidTemperature = primaryFluid.getFluid() + .getTemperature(); + } + + machineTemp = fluidTemperature; // Solely for tricorder info + + machineFocus = getMachineFocus(fluidTemperature); + + inputFocus = this.getInputInformation() + .getFocus(); + + outputFocus = (inputFocus > machineFocus) ? ((inputFocus + machineFocus) / 2.5f) + : inputFocus * (machineFocus / 100); // If input focus > machine focus, divide their sum by 2.5, else + // weigh the former by the latter. This punishes having too low a + // machine focus for low values of input focus + // E.g. An input focus of 50 requires a machine focus of 100 to get an + // output focus of 50, + // whereas an input focus of 60 only requires around 80 + // In general, as input focus increases, output scales better with + // machine focus + + voltageFactor = getVoltageFactor(voltage, this.antennaeTier); + + inputEnergy = this.getInputInformation() + .getEnergy(); + float mass = inputParticle.getMass(); + + // Perhaps divide by mass somehow here too + outputEnergy = (float) calculateOutputParticleEnergy(voltage, inputEnergy, this.antennaeTier); // maybe + // adjust + // behaviour here + + inputRate = this.getInputInformation() + .getRate(); + + outputRate = (int) (inputRate * getOutputRatetio(voltageFactor, this.antennaeTier)); + + if (outputRate == 0) { + stopMachine(SimpleShutDownReason.ofCritical("gtnhlanth.low_input_rate")); + return false; + } + + if (Util.coolantFluidCheck(primaryFluid, CONSUMED_FLUID)) { + + stopMachine(SimpleShutDownReason.ofCritical("gtnhlanth.inscoolant")); + return false; + + } + + primaryFluid.amount -= CONSUMED_FLUID; + + Fluid fluidOutput = BeamlineRecipeLoader.coolantMap.get( + primaryFluid.getFluid() + .getName()); + + if (Objects.isNull(fluidOutput)) return false; + + FluidStack fluidOutputStack = new FluidStack(fluidOutput, CONSUMED_FLUID); + + if (Objects.isNull(fluidOutputStack)) return false; + + this.addFluidOutputs(new FluidStack[] { fluidOutputStack }); + + outputAfterRecipe(); + + return true; + } + + private void outputAfterRecipe() { + + if (!mOutputBeamline.isEmpty()) { + + BeamLinePacket packet = new BeamLinePacket( + new BeamInformation(outputEnergy, outputRate, outputParticle, outputFocus)); + + for (MTEHatchOutputBeamline o : mOutputBeamline) { + + o.q = packet; + } + } + } + + @Override + public void stopMachine() { + + outputFocus = 0; + outputEnergy = 0; + outputParticle = 0; + outputRate = 0; + machineFocus = 0; + machineTemp = 0; + super.stopMachine(); + + } + + @Override + public void stopMachine(ShutDownReason reason) { + + outputFocus = 0; + outputEnergy = 0; + outputParticle = 0; + outputRate = 0; + machineFocus = 0; + machineTemp = 0; + super.stopMachine(reason); + + } + + private BeamInformation getInputInformation() { + + for (MTEHatchInputBeamline in : this.mInputBeamline) { + + if (in.q == null) return new BeamInformation(0, 0, 0, 0); + // if (in.q == null) return new BeamInformation(10000, 10, 0, 90); // TODO temporary for testing purposes + + return in.q.getContent(); + } + return null; + } + + private static float getVoltageFactor(long mEU, int antennaTier) { + + // float factor = (float) Math.pow(1.00004, -mEU * Math.pow(antennaTier, 1.0/3.0) + 80000); + float factor = (float) -Math.pow(1.1, -mEU / 2000 * Math.pow(antennaTier, 2.0 / 3.0)) + 1; // Strictly improves + // with higher tier + // antenna + return (float) Math.max(1.0, factor); + + } + + /* + * private static float getTemperatureFactor(int temperature) { float factor = (float) Math.pow(1.11, 0.18 * + * temperature); return factor; } + */ + private static double calculateOutputParticleEnergy(long voltage, double inputParticleEnergy, int antennaTier) { + + /* + * Energy in general increases as input energy increases, with the relationship between the machine EUt and + * energy being an negative exponential, with a maximum depending on both input particle energy and antenna + * tier. The extent to which the output depends on the former is determined by the cbrt of the latter, meaning + * that increases in antenna tier result in diminishing returns. In the same way, the curve of the output energy + * vs. machine voltage exponential depends on antenna tier, with an increase in antenna tier resulting in a more + * shallow curve up. The effect of this also increases with the tier. LaTeX: + * -\frac{l^{1.11t^{\frac{1}{3}}}}{40000000}\cdot\left(0.15^{\frac{2}{t^{\frac{3}{2}}}}\right)^{\frac{x}{60768}} + * \ +\ \frac{l^{1.11t^{\frac{1}{3}}}}{40000000} + */ + + double energy = (Math.pow(inputParticleEnergy, 1.13 * Math.pow(antennaTier, 4.0 / 9.0)) / 40_000_000) + * (-Math.pow(Math.pow(0.15, 2.0 / (Math.pow(antennaTier, 5.0 / 2.0))), voltage / 60768.0) + 1); // In + // keV + + return energy; + + } + + private static float getMachineFocus(int temperature) { + + return (float) Math.max(Math.min(Math.pow(1.5, -1.0 / 40.0 * (temperature - 480)), 90), 10); + } + + // Punny, right? + private static float getOutputRatetio(float voltageFactor, int antennaTier) { + return (float) (voltageFactor / (10 / Math.pow(2.5, antennaTier))); // Scale ratio with antenna tier, such a + // high + // exponential should be fine so long as + // there + // are only few antenna tiers + } + + @Override + public String[] getStructureDescription(ItemStack arg0) { + return DescTextLocalization.addText("Synchrotron.hint", 12); + } + + @Override + public String[] getInfoData() { + + long storedEnergy = 0; + long maxEnergy = 0; + for (MTEHatchEnergy tHatch : mEnergyHatches) { + if (tHatch.isValid()) { + storedEnergy += tHatch.getBaseMetaTileEntity() + .getStoredEU(); + maxEnergy += tHatch.getBaseMetaTileEntity() + .getEUCapacity(); + } + } + + BeamInformation information = this.getInputInformation(); + + return new String[] { + /* 1 */ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": " + + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(mProgresstime / 20) + + EnumChatFormatting.RESET + + " s / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(mMaxProgresstime / 20) + + EnumChatFormatting.RESET + + " s", + /* 2 */ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": " + + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(storedEnergy) + + EnumChatFormatting.RESET + + " EU / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(maxEnergy) + + EnumChatFormatting.RESET + + " EU", + /* 3 */ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": " + + EnumChatFormatting.RED + + GTUtility.formatNumbers(getActualEnergyUsage()) + + EnumChatFormatting.RESET + + " EU/t", + /* 4 */ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(getMaxInputVoltage()) + + EnumChatFormatting.RESET + + " EU/t(*2A) " + + StatCollector.translateToLocal("GT5U.machines.tier") + + ": " + + EnumChatFormatting.YELLOW + + VN[GTUtility.getTier(getMaxInputVoltage())] + + EnumChatFormatting.RESET, + /* 5 */ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": " + + EnumChatFormatting.RED + + (getIdealStatus() - getRepairStatus()) + + EnumChatFormatting.RESET + + " " + + StatCollector.translateToLocal("GT5U.multiblock.efficiency") + + ": " + + EnumChatFormatting.YELLOW + + Float.toString(mEfficiency / 100.0F) + + EnumChatFormatting.RESET + + " %", + + /* 7 */ EnumChatFormatting.BOLD + StatCollector.translateToLocal("beamline.info") + + ": " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.focus") + ": " // Machine Focus: + + EnumChatFormatting.BLUE + + machineFocus + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.temperature") + ": " // Temperature: + + EnumChatFormatting.DARK_RED + + machineTemp + + EnumChatFormatting.RESET + + " K", // e.g. "137 K" + StatCollector.translateToLocal("beamline.coolusage") + ": " // Coolant Usage: + + EnumChatFormatting.AQUA + + 32_000 + + EnumChatFormatting.RESET + + " kL/s", // 32 kL/s + + /* 8 */ EnumChatFormatting.BOLD + StatCollector.translateToLocal("beamline.in_pre") + + ": " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.particle") + ": " // "Multiblock Beamline Input:" + + EnumChatFormatting.GOLD + + Particle.getParticleFromId(information.getParticleId()) + .getLocalisedName() // e.g. "Electron + // (e-)" + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.energy") + ": " // "Energy:" + + EnumChatFormatting.DARK_RED + + information.getEnergy() + + EnumChatFormatting.RESET + + " keV", // e.g. "10240 keV" + StatCollector.translateToLocal("beamline.focus") + ": " // "Focus:" + + EnumChatFormatting.BLUE + + information.getFocus() + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.amount") + ": " // "Amount:" + + EnumChatFormatting.LIGHT_PURPLE + + information.getRate(), + EnumChatFormatting.BOLD + StatCollector.translateToLocal("beamline.out_pre") // "Multiblock Beamline + // Output:" + + ": " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.particle") + ": " + + EnumChatFormatting.GOLD + + Particle.getParticleFromId(this.outputParticle) + .getLocalisedName() + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.energy") + ": " + + EnumChatFormatting.DARK_RED + + this.outputEnergy * 1000 + + EnumChatFormatting.RESET + + " eV", + StatCollector.translateToLocal( + "beamline.focus") + ": " + EnumChatFormatting.BLUE + this.outputFocus + " " + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.amount") + ": " + + EnumChatFormatting.LIGHT_PURPLE + + this.outputRate, }; + } + + @Override + public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { + + this.mInputBeamline.clear(); + this.mOutputBeamline.clear(); + + this.mAntennaCasings.clear(); + + this.mEnergyHatches.clear(); + this.energyHatchTier = 0; + this.antennaeTier = 0; + + this.glassTier = 0; + + this.outputEnergy = 0; + this.outputRate = 0; + this.outputFocus = 0; + this.outputParticle = 0; + + if (!checkPiece(STRUCTURE_PIECE_ENTRANCE, 16, 3, 1)) return false; + if (!checkPiece(STRUCTURE_PIECE_BASE, 16, 3, 0)) return false; + + return this.mInputBeamline.size() == 1 && this.mOutputBeamline.size() == 1 + && this.mMaintenanceHatches.size() == 1 + && this.mEnergyHatches.size() == 4 + && this.glassTier >= MIN_GLASS_TIER; + } + + @Override + public int getMaxEfficiency(ItemStack aStack) { + return 10000; + } + + @Override + public int getDamageToComponent(ItemStack aStack) { + return 0; + } + + @Override + public boolean explodesOnComponentBreak(ItemStack aStack) { + return false; + } + +} diff --git a/src/main/java/gtnhlanth/common/tileentity/MTETargetChamber.java b/src/main/java/gtnhlanth/common/tileentity/MTETargetChamber.java new file mode 100644 index 0000000000..8545d5e23a --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/MTETargetChamber.java @@ -0,0 +1,480 @@ +package gtnhlanth.common.tileentity; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlockAdder; +import static gregtech.api.enums.GTValues.VN; +import static gregtech.api.enums.HatchElement.Energy; +import static gregtech.api.enums.HatchElement.InputBus; +import static gregtech.api.enums.HatchElement.Maintenance; +import static gregtech.api.enums.HatchElement.OutputBus; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_GLOW; +import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages; +import static gregtech.api.util.GTStructureUtility.buildHatchAdder; +import static gtnhlanth.util.DescTextLocalization.BLUEPRINT_INFO; +import static gtnhlanth.util.DescTextLocalization.addDotText; + +import java.util.ArrayList; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidStack; + +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; + +import bartworks.common.loaders.ItemRegistry; +import gregtech.api.GregTechAPI; +import gregtech.api.enums.TickTime; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.metatileentity.implementations.MTEEnhancedMultiBlockBase; +import gregtech.api.metatileentity.implementations.MTEHatchEnergy; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.GTUtility; +import gregtech.api.util.MultiblockTooltipBuilder; +import gtnhlanth.common.beamline.BeamInformation; +import gtnhlanth.common.beamline.Particle; +import gtnhlanth.common.hatch.MTEBusInputFocus; +import gtnhlanth.common.hatch.MTEHatchInputBeamline; +import gtnhlanth.common.register.LanthItemList; +import gtnhlanth.common.tileentity.recipe.beamline.BeamlineRecipeAdder2; +import gtnhlanth.common.tileentity.recipe.beamline.RecipeTC; +import gtnhlanth.util.DescTextLocalization; + +public class MTETargetChamber extends MTEEnhancedMultiBlockBase<MTETargetChamber> implements ISurvivalConstructable { + + private static final IStructureDefinition<MTETargetChamber> STRUCTURE_DEFINITION; + + private ArrayList<MTEHatchInputBeamline> mInputBeamline = new ArrayList<>(); + + private ArrayList<MTEBusInputFocus> mInputFocus = new ArrayList<>(); + + private static final int CASING_INDEX_FRONT = GTUtility.getCasingTextureIndex(GregTechAPI.sBlockCasings3, 10); // Grate + private static final int CASING_INDEX_CENTRE = GTUtility.getCasingTextureIndex(GregTechAPI.sBlockCasings5, 14); // Shielded + // Acc. + + private float inputEnergy; + private float inputRate; + private int inputParticle; + private float inputFocus; + + // spotless:off + static { + STRUCTURE_DEFINITION = StructureDefinition.<MTETargetChamber>builder() + .addShape( + "base", + new String[][] { + {"ggggg", "gjjjg", "gjbjg", "gjjjg", "ff~ff"}, + {"cslsc", "s-r-s", "srhrs", "s-r-s", "ccccc"}, + {"csssc", "s---s", "s---s", "s---s", "ccccc"}, + {"csssc", "s---s", "s---s", "s---s", "ccccc"}, + {"cstsc", "s-u-s", "suius", "s-u-s", "ccccc"}, + {"ggggg", "gjjjg", "gjojg", "gjjjg", "ggggg"}}) + + .addElement('g', ofBlock(GregTechAPI.sBlockCasings3, 10)) //Grate casing + .addElement( + 'f', + buildHatchAdder(MTETargetChamber.class).atLeast(Maintenance, Energy) + .casingIndex(CASING_INDEX_FRONT).dot(2).buildAndChain(ofBlock(GregTechAPI.sBlockCasings3, 10))) + + .addElement('j', ofBlockAdder(MTETargetChamber::addGlass, ItemRegistry.bw_glasses[0], 1)) + .addElement('b', buildHatchAdder(MTETargetChamber.class).hatchClass(MTEHatchInputBeamline.class).casingIndex(CASING_INDEX_CENTRE).dot(5).adder(MTETargetChamber::addBeamLineInputHatch).build()) + .addElement('c', ofBlock(LanthItemList.SHIELDED_ACCELERATOR_CASING, 0)) + + .addElement('l', buildHatchAdder(MTETargetChamber.class).hatchClass(MTEBusInputFocus.class).casingIndex(CASING_INDEX_CENTRE).dot(1).adder(MTETargetChamber::addFocusInputHatch).build()) + + .addElement('t', buildHatchAdder(MTETargetChamber.class).atLeast(InputBus).casingIndex(CASING_INDEX_CENTRE).dot(3).build()) + .addElement('s', ofBlock(LanthItemList.SHIELDED_ACCELERATOR_GLASS, 0)) + .addElement('r', ofBlock(LanthItemList.FOCUS_MANIPULATION_CASING, 0)) + .addElement('h', ofBlock(LanthItemList.FOCUS_HOLDER, 0)) + .addElement('u', ofBlock(LanthItemList.TARGET_RECEPTACLE_CASING, 0)) + .addElement('i', ofBlock(LanthItemList.TARGET_HOLDER, 0)) + .addElement('o', buildHatchAdder(MTETargetChamber.class).atLeast(OutputBus).casingIndex(CASING_INDEX_CENTRE).dot(4).build()) + + .build(); + } + //spotless:on + + private boolean addGlass(Block block, int meta) { + return block == ItemRegistry.bw_glasses[0]; + } + + private boolean addBeamLineInputHatch(IGregTechTileEntity te, int casingIndex) { + + if (te == null) return false; + + IMetaTileEntity mte = te.getMetaTileEntity(); + + if (mte == null) return false; + + if (mte instanceof MTEHatchInputBeamline) { + return this.mInputBeamline.add((MTEHatchInputBeamline) mte); + } + + return false; + } + + private boolean addFocusInputHatch(IGregTechTileEntity te, int casingIndex) { + + if (te == null) return false; + + IMetaTileEntity mte = te.getMetaTileEntity(); + + if (mte == null) return false; + + if (mte instanceof MTEBusInputFocus) { + return this.mInputFocus.add((MTEBusInputFocus) mte); + } + + return false; + } + + public MTETargetChamber(int id, String name, String nameRegional) { + super(id, name, nameRegional); + } + + public MTETargetChamber(String name) { + super(name); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity te) { + return new MTETargetChamber(this.mName); + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int colorIndex, boolean active, boolean redstoneLevel) { + // Placeholder + if (side == facing) { + if (active) return new ITexture[] { casingTexturePages[0][47], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW) + .extFacing() + .glow() + .build() }; + return new ITexture[] { casingTexturePages[0][47], TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(OVERLAY_FRONT_OIL_CRACKER_GLOW) + .extFacing() + .glow() + .build() }; + } + return new ITexture[] { casingTexturePages[0][47] }; + } + + @Override + protected MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Collision Chamber") + .addInfo("Controller block for the Target Chamber") + .addInfo("Hitting things with other things") + + .addInfo(BLUEPRINT_INFO) + .addInfo(DescTextLocalization.BEAMLINE_SCANNER_INFO) + .addSeparator() + .beginStructureBlock(5, 5, 6, true) + .addController("Front bottom") + .addCasingInfoExactly("Grate Machine Casing", 29, false) + .addCasingInfoExactly("Shielded Accelerator Casing", 28, false) + .addCasingInfoExactly("Borosilicate Glass", 16, true) + .addCasingInfoExactly(LanthItemList.SHIELDED_ACCELERATOR_GLASS.getLocalizedName(), 34, false) + .addCasingInfoExactly(LanthItemList.TARGET_RECEPTACLE_CASING.getLocalizedName(), 4, false) + .addCasingInfoExactly(LanthItemList.FOCUS_MANIPULATION_CASING.getLocalizedName(), 4, false) + .addCasingInfoExactly(LanthItemList.FOCUS_HOLDER.getLocalizedName(), 1, false) + .addCasingInfoExactly(LanthItemList.TARGET_HOLDER.getLocalizedName(), 1, false) + .addOtherStructurePart("Focus Input Bus", addDotText(1)) + .addMaintenanceHatch(addDotText(2)) + .addEnergyHatch(addDotText(2)) + .addInputBus(addDotText(3)) + .addOutputBus(addDotText(4)) + .addOtherStructurePart("Beamline Input Hatch", addDotText(5)) + .toolTipFinisher("GTNH: Lanthanides"); + return tt; + } + + @Override + public void construct(ItemStack stackSize, boolean hintsOnly) { + buildPiece("base", stackSize, hintsOnly, 2, 4, 0); + + } + + @Override + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + if (mMachine) return -1; + return survivialBuildPiece("base", stackSize, 2, 4, 0, elementBudget, env, false, true); + } + + @Override + public IStructureDefinition<MTETargetChamber> getStructureDefinition() { + return STRUCTURE_DEFINITION; + } + + @Override + public RecipeMap<?> getRecipeMap() { + return BeamlineRecipeAdder2.instance.TargetChamberRecipes; + } + + @Override + public boolean checkRecipe(ItemStack itemStack) { + + inputEnergy = 0; + inputRate = 0; + inputParticle = 0; + inputFocus = 0; + + ArrayList<ItemStack> tItems = this.getStoredInputs(); + ItemStack tFocusItem = this.getFocusItemStack(); + + ItemStack tFocusItemZeroDamage = null; + + if (tFocusItem != null) { + + tFocusItemZeroDamage = tFocusItem.copy(); + tFocusItemZeroDamage.setItemDamage(0); + } + + ArrayList<ItemStack> tItemsWithFocusItem = new ArrayList<>(); + tItemsWithFocusItem.add(tFocusItemZeroDamage); + tItemsWithFocusItem.addAll(tItems); + + long tVoltage = this.getMaxInputVoltage(); + + ItemStack[] tItemsArray = tItems.toArray(new ItemStack[0]); + + ItemStack[] tItemsWithFocusItemArray = tItemsWithFocusItem.toArray(new ItemStack[0]); + + RecipeTC tRecipe = (RecipeTC) BeamlineRecipeAdder2.instance.TargetChamberRecipes.findRecipeQuery() + .items(tItemsWithFocusItemArray) + .voltage(tVoltage) + .filter((GTRecipe recipe) -> { + + RecipeTC recipeTc = (RecipeTC) recipe; + + BeamInformation inputInfo = this.getInputInformation(); + + int particle = recipeTc.particleId; + + return (particle == inputInfo.getParticleId() + && !(inputInfo.getEnergy() < recipeTc.minEnergy || inputInfo.getEnergy() > recipeTc.maxEnergy)); + + }) + .find(); + + if (tRecipe == null || !tRecipe.isRecipeInputEqual(true, new FluidStack[] {}, tItemsWithFocusItemArray)) + return false; + + if (tRecipe.focusItem != null) { + if (tRecipe.focusItem.getItem() != tFocusItem.getItem()) return false; + } + + this.mEfficiency = (10000 - (this.getIdealStatus() - this.getRepairStatus()) * 1000); + this.mEfficiencyIncrease = 10000; + + BeamInformation inputInfo = this.getInputInformation(); + + if (inputInfo == null) return false; + + inputEnergy = inputInfo.getEnergy(); + inputRate = inputInfo.getRate(); + inputParticle = inputInfo.getParticleId(); + inputFocus = inputInfo.getFocus(); + + if (inputEnergy < tRecipe.minEnergy || inputEnergy > tRecipe.maxEnergy) return false; + + if (inputFocus < tRecipe.minFocus) return false; + + if (inputParticle != tRecipe.particleId) return false; + + this.mMaxProgresstime = Math.max(Math.round((tRecipe.amount / inputRate * 5 * TickTime.SECOND)), 1); // 5 + // seconds + // per + // integer multiple + // over the rate. E.g., 100a, 10r + // would equal 50 seconds + if (this.mMaxProgresstime == Integer.MAX_VALUE - 1 && this.mEUt == Integer.MAX_VALUE - 1) return false; + + mEUt = (int) -tVoltage; + if (this.mEUt > 0) this.mEUt = (-this.mEUt); + + this.mOutputItems = tRecipe.mOutputs; + + if (tRecipe.focusItem != null) // Recipe actually uses the mask, can also assume machine mask item is nonnull + // due to above conditions + mInputFocus.get(0) + .depleteFocusDurability(1); + + this.updateSlots(); + + return true; + } + + private BeamInformation getInputInformation() { + + for (MTEHatchInputBeamline in : this.mInputBeamline) { + + if (in.q == null) return new BeamInformation(0, 0, 0, 0); + // if (in.q == null) return new BeamInformation(10, 10, Particle.PHOTON.ordinal(), 90); // temporary + // for + // testing purposes + + return in.q.getContent(); + } + return null; + } + + private ItemStack getFocusItemStack() { + + for (MTEBusInputFocus hatch : this.mInputFocus) { + return hatch.getContentUsageSlots() + .get(0); + } + + return null; + + } + + @Override + public boolean checkMachine(IGregTechTileEntity arg0, ItemStack arg1) { + + mInputBeamline.clear(); + mInputFocus.clear(); + + if (!checkPiece("base", 2, 4, 0)) return false; + + return this.mInputBeamline.size() == 1 && this.mMaintenanceHatches.size() == 1 + && this.mInputBusses.size() == 1 + && this.mOutputBusses.size() == 1 + && this.mInputFocus.size() == 1; + } + + @Override + public boolean explodesOnComponentBreak(ItemStack arg0) { + return false; + } + + @Override + public int getDamageToComponent(ItemStack arg0) { + return 0; + } + + @Override + public int getMaxEfficiency(ItemStack arg0) { + return 10000; + } + + @Override + public boolean isCorrectMachinePart(ItemStack arg0) { + return true; + } + + @Override + public String[] getStructureDescription(ItemStack arg0) { + return DescTextLocalization.addText("TargetChamber.hint", 13); + } + + @Override + public String[] getInfoData() { + + long storedEnergy = 0; + long maxEnergy = 0; + for (MTEHatchEnergy tHatch : mEnergyHatches) { + if (tHatch.isValid()) { + storedEnergy += tHatch.getBaseMetaTileEntity() + .getStoredEU(); + maxEnergy += tHatch.getBaseMetaTileEntity() + .getEUCapacity(); + } + } + + BeamInformation information = this.getInputInformation(); + + return new String[] { + /* 1 */ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": " + + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(mProgresstime / 20) + + EnumChatFormatting.RESET + + " s / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(mMaxProgresstime / 20) + + EnumChatFormatting.RESET + + " s", + /* 2 */ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": " + + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(storedEnergy) + + EnumChatFormatting.RESET + + " EU / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(maxEnergy) + + EnumChatFormatting.RESET + + " EU", + /* 3 */ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": " + + EnumChatFormatting.RED + + GTUtility.formatNumbers(getActualEnergyUsage()) + + EnumChatFormatting.RESET + + " EU/t", + /* 4 */ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(getMaxInputVoltage()) + + EnumChatFormatting.RESET + + " EU/t(*2A) " + + StatCollector.translateToLocal("GT5U.machines.tier") + + ": " + + EnumChatFormatting.YELLOW + + VN[GTUtility.getTier(getMaxInputVoltage())] + + EnumChatFormatting.RESET, + /* 5 */ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": " + + EnumChatFormatting.RED + + (getIdealStatus() - getRepairStatus()) + + EnumChatFormatting.RESET + + " " + + StatCollector.translateToLocal("GT5U.multiblock.efficiency") + + ": " + + EnumChatFormatting.YELLOW + + Float.toString(mEfficiency / 100.0F) + + EnumChatFormatting.RESET + + " %", + + /* 6 */ EnumChatFormatting.BOLD + StatCollector.translateToLocal("beamline.in_pre") + + ": " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.particle") + ": " // "Multiblock Beamline Input:" + + EnumChatFormatting.GOLD + + Particle.getParticleFromId(information.getParticleId()) + .getLocalisedName() // e.g. "Electron + // (e-)" + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.energy") + ": " // "Energy:" + + EnumChatFormatting.DARK_RED + + information.getEnergy() * 1000 // In line with the synchrotron's output + + EnumChatFormatting.RESET + + " eV", // e.g. "10240 eV" + StatCollector.translateToLocal("beamline.focus") + ": " // "Focus:" + + EnumChatFormatting.BLUE + + information.getFocus() + + " " + + EnumChatFormatting.RESET, + StatCollector.translateToLocal("beamline.amount") + ": " // "Amount:" + + EnumChatFormatting.LIGHT_PURPLE + + information.getRate(), }; + } + +} diff --git a/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/BeamlineRecipeAdder2.java b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/BeamlineRecipeAdder2.java new file mode 100644 index 0000000000..dad71375c3 --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/BeamlineRecipeAdder2.java @@ -0,0 +1,165 @@ +package gtnhlanth.common.tileentity.recipe.beamline; + +import java.util.Arrays; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.StatCollector; + +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.recipe.RecipeMapBackend; +import gregtech.api.recipe.RecipeMapBuilder; +import gregtech.api.util.GTUtility; +import gtnhlanth.common.beamline.Particle; + +public class BeamlineRecipeAdder2 { + + public static final BeamlineRecipeAdder2 instance = new BeamlineRecipeAdder2(); + + public final RecipeMap<RecipeMapBackend> SourceChamberRecipes = RecipeMapBuilder.of("gtnhlanth.recipe.sc") + .minInputs(0, 0) + .maxIO(1, 2, 0, 0) + .amperage(1) + .frontend(SourceChamberFrontend::new) + .progressBar(GTUITextures.PROGRESSBAR_ASSEMBLY_LINE_1) + .neiSpecialInfoFormatter((recipeInfo) -> { + + RecipeSC recipe = (RecipeSC) recipeInfo.recipe; + + float focus = recipe.focus; + float maxEnergy = recipe.maxEnergy; + + int amount = recipe.rate; + + Particle particle = Particle.getParticleFromId(recipe.particleId); + + return Arrays.asList( + + // StatCollector.translateToLocal("beamline.particle") + ": " + particle.getLocalisedName(), + + StatCollector.translateToLocal("beamline.energy") + ": <=" + + GTUtility.formatNumbers(Math.min(maxEnergy, particle.maxSourceEnergy())) + + " keV", + + StatCollector.translateToLocal("beamline.focus") + ": " + GTUtility.formatNumbers(focus), + + StatCollector.translateToLocal("beamline.rate") + ": " + GTUtility.formatNumbers(amount) + + ); + }) + // .slotOverlays(null) + + .build(); + + public final RecipeMap<RecipeMapBackend> TargetChamberRecipes = RecipeMapBuilder.of("gtnhlanth.recipe.tc") + .minInputs(0, 0) + .maxIO(3, 4, 0, 0) + .frontend(TargetChamberFrontend::new) + .neiSpecialInfoFormatter(((recipeInfo) -> { + + RecipeTC recipe = (RecipeTC) recipeInfo.recipe; + + float minEnergy = recipe.minEnergy; + float maxEnergy = recipe.maxEnergy; + + float minFocus = recipe.minFocus; + + float amount = recipe.amount; + + Particle particle = Particle.getParticleFromId(recipe.particleId); + + return Arrays.asList( + + // StatCollector.translateToLocal("beamline.particle") + ": " + particle.getLocalisedName(), + + StatCollector.translateToLocal("beamline.energy") + ": " + + GTUtility.formatNumbers(minEnergy * 1000) + + "-" + + GTUtility.formatNumbers(maxEnergy * 1000) + + " eV", // Note the eV unit + + StatCollector.translateToLocal("beamline.focus") + ": >=" + GTUtility.formatNumbers(minFocus), + + StatCollector.translateToLocal("beamline.amount") + ": " + GTUtility.formatNumbers(amount) + + ); + })) + // .slotOverlays(null) + .progressBar(GTUITextures.PROGRESSBAR_ASSEMBLY_LINE_1) + .progressBarPos(108, 22) + .neiTransferRect(100, 22, 28, 18) + .build(); + + /*** + * + * @param itemInputs - duh + * @param itemOutputs - duh + * @param particleId - The ID of the {@link Particle} generated by the recipe. + * It is recommended to use Particle#ordinal() + * @param rate - The rate/amount of particles generated + * @param maxEnergy - The maximum energy particles generated by this recipe can possess (keV). Set this value >= + * max particle energy to limit it to the latter + * @param focus - Focus of the particle generated + * @param energyRatio - Set high for little-to-no EUt energy scaling, low for the opposite + * @param minEUt - Minimum EUt required for the recipe. ! May not output if input energy is equal to minimum ! + */ + public boolean addSourceChamberRecipe(ItemStack[] itemInputs, ItemStack[] itemOutputs, int particleId, int rate, + float maxEnergy, float focus, float energyRatio, int minEUt) { + + return (SourceChamberRecipes.addRecipe( + new RecipeSC( + false, + itemInputs, + itemOutputs, + null, + new int[] {}, + null, + null, + 20, + minEUt, + particleId, + rate, + maxEnergy, + focus, + energyRatio)) + != null); + } + + /*** + * + * @param itemInput - The item to be used as a target. Should have durability + * @param itemOutput - duh + * @param particleId - The ID of the {@link Particle} used by the recipe. It + * is recommended to use Particle#ordinal() + * @param amount - The total amount of particles required for the recipe to come to completion. The duration of + * the recipe will be determined by this and the input particle rate. + * @param minEnergy - The minimum energy amount required by this recipe in keV (inclusive) + * @param maxEnergy - The maximum energy amount allowed by this recipe in keV (inclusive) + * @param minFocus - Minimum focus allowed by the recipe + * @param energyRatio - Set high for little-to-no EUt energy scaling, low for the opposite + * @param minEUt - Minimum EUt required for the recipe to start + */ + + public boolean addTargetChamberRecipe(ItemStack itemInput, ItemStack itemOutput, ItemStack itemFocus, + int particleId, int amount, float minEnergy, float maxEnergy, float minFocus, float energyRatio, int minEUt) { + + return (TargetChamberRecipes.addRecipe( + new RecipeTC( + false, + itemInput, + itemOutput, + itemFocus, + particleId, + amount, + minEnergy, + maxEnergy, + minFocus, + energyRatio, + minEUt), + false, + false, + false) != null); + + } + +} diff --git a/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/BeamlineRecipeLoader.java b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/BeamlineRecipeLoader.java new file mode 100644 index 0000000000..d71b9a571e --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/BeamlineRecipeLoader.java @@ -0,0 +1,193 @@ +package gtnhlanth.common.tileentity.recipe.beamline; + +import java.util.Arrays; +import java.util.HashMap; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; + +import gregtech.api.enums.ItemList; +import gregtech.api.enums.Materials; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.util.GTOreDictUnificator; +import gregtech.api.util.GTUtility; +import gtPlusPlus.core.material.MaterialsElements; +import gtnhlanth.common.beamline.Particle; +import gtnhlanth.common.item.MaskList; +import gtnhlanth.common.register.LanthItemList; +import gtnhlanth.common.register.WerkstoffMaterialPool; + +public class BeamlineRecipeLoader { + + public static final HashMap<String, Fluid> coolantMap = new HashMap<>(); + + private static final ItemList[] VIABLE_WAFERS = new ItemList[] { ItemList.Circuit_Silicon_Wafer, + ItemList.Circuit_Silicon_Wafer2, ItemList.Circuit_Silicon_Wafer3, ItemList.Circuit_Silicon_Wafer4, + ItemList.Circuit_Silicon_Wafer5, ItemList.Circuit_Silicon_Wafer6, ItemList.Circuit_Silicon_Wafer7 }; + + public static void load() { + + /* + * Coolant list + */ + + coolantMap.put( + Materials.LiquidNitrogen.getGas(1L) + .getFluid() + .getName(), + Materials.Nitrogen.getGas(1L) + .getFluid()); + coolantMap.put( + Materials.LiquidOxygen.getGas(1L) + .getFluid() + .getName(), + Materials.Oxygen.getGas(1L) + .getFluid()); + coolantMap.put("ic2coolant", FluidRegistry.getFluid("ic2hotcoolant")); + coolantMap.put( + Materials.SuperCoolant.getFluid(1L) + .getFluid() + .getName(), + Materials.Water.getFluid(1L) + .getFluid()); + + /* + * ELECTRON + */ + BeamlineRecipeAdder2.instance.addSourceChamberRecipe( + new ItemStack[] { GTOreDictUnificator.get(OrePrefixes.stick, Materials.Tungsten, 1) }, + null, + Particle.ELECTRON.ordinal(), + 20, + 1000, + 98, + 0.1f, + 7680); + + BeamlineRecipeAdder2.instance.addSourceChamberRecipe( + new ItemStack[] { WerkstoffMaterialPool.LanthanumHexaboride.get(OrePrefixes.stickLong, 1) }, + null, + Particle.ELECTRON.ordinal(), + 60, + 5000, + 99, + 0.3f, + 7680); + + /* + * NEUTRON + */ + BeamlineRecipeAdder2.instance.addSourceChamberRecipe( + new ItemStack[] { MaterialsElements.getInstance().CALIFORNIUM.getDust(1) }, + null, + Particle.NEUTRON.ordinal(), + 10, + 9000, + 95, + 999, + 1920); + + /* + * ALPHA + */ + BeamlineRecipeAdder2.instance.addSourceChamberRecipe( + new ItemStack[] { Materials.Uranium.getDust(1) }, + new ItemStack[] { WerkstoffMaterialPool.Thorium234.get(OrePrefixes.dust, 1) }, + Particle.ALPHA.ordinal(), + 1, + 4270, + 90, + 999, + 480); + + /* + * TARGET CHAMBER + */ + + for (MaskList mask : MaskList.values()) { + + if (mask.getProducedItem() == null) // Blank or error + continue; + + int index = 0; + for (ItemList wafer : VIABLE_WAFERS) { + + index++; + + if (!Arrays.asList(mask.getForbiddenWafers()) + .contains(wafer)) { + + BeamlineRecipeAdder2.instance.addTargetChamberRecipe( + wafer.get(1), + GTUtility.copyAmountUnsafe((int) Math.pow(2, index + 2), mask.getProducedItem()), + new ItemStack(LanthItemList.maskMap.get(mask), 0), + 1, + mask.getBaselineAmount() * (int) Math.pow(Math.sqrt(3), index - 1), // 3x recipe amount increase + // per 2 increases in wafer + // tier. This greatly + // incentivises the use of + // higher tier boule wafer + // recipes + mask.getMinEnergy(), + mask.getMaxEnergy(), + mask.getMinFocus(), + 1, + 1920); + + } + + } + + /* + * if (!Arrays.asList(MaskList.CPU.getForbiddenWafers()).contains(wafer)) { + * BeamlineRecipeAdder.instance.addTargetChamberRecipe( wafer.get(1), GT_Utility.copyAmountUnsafe((int) + * Math.pow(2, index + 2), ItemList.Circuit_Wafer_CPU.get(1)), //Varies new + * ItemStack(LanthItemList.maskMap.get(MaskList.CPU), 0), // Varies 0, 10 * (int) Math.pow(2, index - 1), // + * Varies 1, //Varies 10000000, //Varies 50, //Varies 1, 1920 ); } /* PPIC + */ + + /* + * if (!Arrays.asList(MaskList.PPIC.getForbiddenWafers()).contains(wafer)) { + * GTLog.out.print("Adding recipe for PPIC with " + wafer.get(1).getUnlocalizedName() + " amount: " + 40 * + * (int) Math.pow(2, index - 1)); BeamlineRecipeAdder.instance.addTargetChamberRecipe( wafer.get(1), + * ItemList.Circuit_Wafer_PPIC.get((int) Math.pow(2, index + 2)), //Varies new + * ItemStack(LanthItemList.maskMap.get(MaskList.PPIC), 0), // Varies 0, 40 * (int) Math.pow(2, index - 1), + * // Varies 1, //Varies 10000000, //Varies 50, //Varies 1, 1920 ); } + */ + + } + /* + * BeamlineRecipeAdder2.instance.addTargetChamberRecipe( new ItemStack(Items.coal, 1), new + * ItemStack(Items.diamond, 1), null, 1, 20, 100, 1000, 60, 1, 1920); + * BeamlineRecipeAdder2.instance.addTargetChamberRecipe( new ItemStack(Items.coal, 1), new + * ItemStack(Items.cooked_chicken, 1), null, 1, 20, 1, 10, 60, 1, 1920); + */ + + BeamlineRecipeAdder2.instance.addTargetChamberRecipe( + new ItemStack(Items.chicken, 1), + new ItemStack(Items.cooked_chicken), + null, + Particle.PHOTON.ordinal(), + 400, + 5, + 20, + 80, + 1, + 7864320); + + BeamlineRecipeAdder2.instance.addTargetChamberRecipe( + new ItemStack(Items.chicken, 1), + new ItemStack(Items.egg), + null, + Particle.PHOTON.ordinal(), + 400, + 21, + 600, + 80, + 1, + 7864320); + + } +} diff --git a/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/RecipeSC.java b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/RecipeSC.java new file mode 100644 index 0000000000..979cb6a8bb --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/RecipeSC.java @@ -0,0 +1,52 @@ +package gtnhlanth.common.tileentity.recipe.beamline; + +import java.util.ArrayList; +import java.util.Arrays; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import gregtech.api.util.GTRecipe; +import gregtech.api.util.GTUtility; +import gtnhlanth.common.register.LanthItemList; + +public class RecipeSC extends GTRecipe { + + public int particleId; + public int rate; + public float maxEnergy; + public float focus; + public float energyRatio; + + public RecipeSC(boolean aOptimize, ItemStack[] aInputs, ItemStack[] aOutputs, Object aSpecialItems, int[] aChances, + FluidStack[] aFluidInputs, FluidStack[] aFluidOutputs, int aDuration, int aEUt, int particleId, int rate, + float maxEnergy, float focus, float energyRatio) { + + super(aOptimize, aInputs, aOutputs, null, aChances, null, null, aDuration, aEUt, 0); + + this.particleId = particleId; + this.rate = rate; + this.maxEnergy = maxEnergy; + this.focus = focus; + this.energyRatio = energyRatio; + } + + @Override + public ItemStack getRepresentativeOutput(int aIndex) { + + ArrayList<ItemStack> mOutputsWithParticle = new ArrayList<>(); + + ItemStack particleStack = new ItemStack(LanthItemList.PARTICLE_ITEM); + + Items.ender_pearl.setDamage(particleStack, this.particleId); + + mOutputsWithParticle.addAll(Arrays.asList(mOutputs)); + mOutputsWithParticle.add(particleStack); + + ItemStack[] mOutputsWithParticleArray = mOutputsWithParticle.toArray(new ItemStack[0]); + + if (aIndex < 0 || aIndex >= mOutputsWithParticleArray.length) return null; + return GTUtility.copyOrNull(mOutputsWithParticleArray[aIndex]); + } +} diff --git a/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/RecipeTC.java b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/RecipeTC.java new file mode 100644 index 0000000000..30be015abb --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/RecipeTC.java @@ -0,0 +1,71 @@ +package gtnhlanth.common.tileentity.recipe.beamline; + +import java.util.ArrayList; +import java.util.Arrays; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; + +import gregtech.api.util.GTRecipe; +import gregtech.api.util.GTUtility; +import gtnhlanth.common.register.LanthItemList; + +public class RecipeTC extends GTRecipe { + + public int particleId; + public int amount; + + public float minEnergy; + public float maxEnergy; + + public float minFocus; + public float energyRatio; + + public ItemStack focusItem; + + public RecipeTC(boolean aOptimize, ItemStack aInput, ItemStack aOutput, ItemStack aFocusItem, int particleId, + int amount, float minEnergy, float maxEnergy, float minFocus, float energyRatio, int aEUt) { + + super( + aOptimize, + new ItemStack[] { aFocusItem, aInput }, + new ItemStack[] { aOutput }, + null, + null, + null, + null, + 1, + aEUt, + 0); + + this.particleId = particleId; + this.amount = amount; + + this.minEnergy = minEnergy; + this.maxEnergy = maxEnergy; + + this.minFocus = minFocus; + + this.energyRatio = energyRatio; + + this.focusItem = aFocusItem; + } + + @Override + public ItemStack getRepresentativeInput(int aIndex) { + + ArrayList<ItemStack> mInputsWithParticle = new ArrayList<>(); + + ItemStack particleStack = new ItemStack(LanthItemList.PARTICLE_ITEM); + Items.ender_pearl.setDamage(particleStack, this.particleId); + + mInputsWithParticle.add(particleStack); + mInputsWithParticle.addAll(Arrays.asList(mInputs)); + + ItemStack[] mInputsWithParticleArray = mInputsWithParticle.toArray(new ItemStack[0]); + + if (aIndex < 0 || aIndex >= mInputsWithParticleArray.length) return null; + return GTUtility.copyOrNull(mInputsWithParticleArray[aIndex]); + } + +} diff --git a/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/SourceChamberFrontend.java b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/SourceChamberFrontend.java new file mode 100644 index 0000000000..3d8a3abfd1 --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/SourceChamberFrontend.java @@ -0,0 +1,24 @@ +package gtnhlanth.common.tileentity.recipe.beamline; + +import gregtech.api.recipe.BasicUIPropertiesBuilder; +import gregtech.api.recipe.NEIRecipePropertiesBuilder; +import gregtech.api.recipe.RecipeMapFrontend; +import gregtech.nei.RecipeDisplayInfo; + +public class SourceChamberFrontend extends RecipeMapFrontend { + + public SourceChamberFrontend(BasicUIPropertiesBuilder uiPropertiesBuilder, + NEIRecipePropertiesBuilder neiPropertiesBuilder) { + super(uiPropertiesBuilder, neiPropertiesBuilder); + } + + @Override + public void drawDescription(RecipeDisplayInfo recipeInfo) { + drawEnergyInfo(recipeInfo); + // drawDurationInfo(recipeInfo); Unnecessary and misleading + drawSpecialInfo(recipeInfo); + drawMetadataInfo(recipeInfo); + drawRecipeOwnerInfo(recipeInfo); + } + +} diff --git a/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/TargetChamberFrontend.java b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/TargetChamberFrontend.java new file mode 100644 index 0000000000..87852381e6 --- /dev/null +++ b/src/main/java/gtnhlanth/common/tileentity/recipe/beamline/TargetChamberFrontend.java @@ -0,0 +1,109 @@ +package gtnhlanth.common.tileentity.recipe.beamline; + +import static gregtech.api.util.GTUtility.trans; + +import java.util.List; + +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; + +import com.gtnewhorizons.modularui.api.math.Pos2d; + +import gregtech.api.recipe.BasicUIPropertiesBuilder; +import gregtech.api.recipe.NEIRecipePropertiesBuilder; +import gregtech.api.recipe.RecipeMapFrontend; +import gregtech.api.util.GTUtility; +import gregtech.api.util.OverclockCalculator; +import gregtech.common.gui.modularui.UIHelper; +import gregtech.nei.GTNEIDefaultHandler; +import gregtech.nei.RecipeDisplayInfo; +import gtnhlanth.util.Util; + +public class TargetChamberFrontend extends RecipeMapFrontend { + + public TargetChamberFrontend(BasicUIPropertiesBuilder uiPropertiesBuilder, + NEIRecipePropertiesBuilder neiPropertiesBuilder) { + super(uiPropertiesBuilder, neiPropertiesBuilder); + } + + public void drawDescription(RecipeDisplayInfo recipeInfo) { + drawEnergyInfo(recipeInfo); + // drawDurationInfo(recipeInfo); + drawSpecialInfo(recipeInfo); + drawMetadataInfo(recipeInfo); + drawRecipeOwnerInfo(recipeInfo); + } + + @Override + protected void drawNEIOverlayForInput(GTNEIDefaultHandler.FixedPositionedStack stack) { + if (stack.isNotConsumed()) { // The stack actually takes damage, but is technically still not considered to be + // consumed by the code + drawNEIOverlayText("PC", stack); + } + } + + @Override + protected List<String> handleNEIItemInputTooltip(List<String> currentTip, + GTNEIDefaultHandler.FixedPositionedStack pStack) { + if (pStack.isNotConsumed()) { // See above + currentTip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("gtnhlanth.tt.pc")); // Partially + // consumed: + // Takes damage + // in the + // process + } + return currentTip; + } + + @Override + public void drawEnergyInfo(RecipeDisplayInfo recipeInfo) { + if (recipeInfo.calculator.getConsumption() <= 0) return; + + // recipeInfo.drawText(trans("152", "Total: ") + getTotalPowerString(recipeInfo.calculator)); + + recipeInfo.drawText(trans("153", "Usage: ") + getEUtDisplay(recipeInfo.calculator)); + recipeInfo.drawText(trans("154", "Voltage: ") + getVoltageString(recipeInfo.calculator)); + recipeInfo.drawText(trans("155", "Amperage: ") + getAmperageString(recipeInfo.calculator)); + + } + + @Override + public List<Pos2d> getItemOutputPositions(int itemOutputCount) { + return UIHelper.getGridPositions(itemOutputCount, 128, 24, 1, 3); // Make output items display vertically, not + // in a square + } + + @Override + public List<Pos2d> getItemInputPositions(int itemInputCount) { + + /* + * Pos2d posParticle = new Pos2d(8, 28); // Particle item ArrayList<Pos2d> posList = new ArrayList<>(); + * posList.add(posParticle); posList.addAll(UIHelper.getGridPositions(itemInputCount - 1, 36, 28, 3)); + */ + + List<Pos2d> posList = Util.getGridPositions(itemInputCount, 8, 20, 3, 1, 20); + return posList; + } + + private String getEUtDisplay(OverclockCalculator calculator) { + return getEUtWithoutTier(calculator); + } + + private String getEUtWithoutTier(OverclockCalculator calculator) { + return GTUtility.formatNumbers(calculator.getConsumption()) + " EU/t"; + } + + private String getVoltageString(OverclockCalculator calculator) { + long voltage = computeVoltageForEURate(calculator.getConsumption()); + return GTUtility.formatNumbers(voltage) + " EU/t" + GTUtility.getTierNameWithParentheses(voltage); + } + + private long computeVoltageForEURate(long euPerTick) { + return euPerTick; + } + + private String getAmperageString(OverclockCalculator calculator) { + return GTUtility.formatNumbers(1); + } + +} |