diff options
Diffstat (limited to 'src/main/java/gregtech/common')
5 files changed, 1373 insertions, 0 deletions
diff --git a/src/main/java/gregtech/common/GT_Client.java b/src/main/java/gregtech/common/GT_Client.java index 69fc98212f..9de59e8661 100644 --- a/src/main/java/gregtech/common/GT_Client.java +++ b/src/main/java/gregtech/common/GT_Client.java @@ -97,6 +97,7 @@ import gregtech.common.render.GT_MultiTile_Renderer; import gregtech.common.render.GT_PollutionRenderer; import gregtech.common.render.GT_RenderDrone; import gregtech.common.render.GT_Renderer_Block; +import gregtech.common.render.GT_WormholeRenderer; import gregtech.common.render.items.GT_MetaGenerated_Item_Renderer; import gregtech.common.tileentities.debug.GT_MetaTileEntity_AdvDebugStructureWriter; import gregtech.loaders.ExtraIcons; @@ -624,6 +625,7 @@ public class GT_Client extends GT_Proxy implements Runnable { new GT_MultiTile_Renderer(); new GT_RenderDrone(); new GT_LaserRenderer(); + new GT_WormholeRenderer(); metaGeneratedItemRenderer = new GT_MetaGenerated_Item_Renderer(); for (GT_MetaGenerated_Item item : GT_MetaGenerated_Item.sInstances.values()) { metaGeneratedItemRenderer.registerItem(item); diff --git a/src/main/java/gregtech/common/blocks/GT_WormholeRenderBlock.java b/src/main/java/gregtech/common/blocks/GT_WormholeRenderBlock.java new file mode 100644 index 0000000000..1c6e434477 --- /dev/null +++ b/src/main/java/gregtech/common/blocks/GT_WormholeRenderBlock.java @@ -0,0 +1,75 @@ +package gregtech.common.blocks; + +import java.util.ArrayList; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.common.tileentities.render.TileWormhole; + +public class GT_WormholeRenderBlock extends Block { + + public GT_WormholeRenderBlock() { + super(Material.iron); + this.setResistance(20f); + this.setHardness(-1.0f); + // this.setCreativeTab(TecTech.creativeTabTecTech); + this.setBlockName("WormholeRenderer"); + this.setLightLevel(100.0f); + GameRegistry.registerBlock(this, getUnlocalizedName()); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerBlockIcons(IIconRegister iconRegister) { + blockIcon = iconRegister.registerIcon("gregtech:iconsets/TRANSPARENT"); + } + + @Override + public String getUnlocalizedName() { + return "gt.wormholerenderer"; + } + + @Override + public boolean isOpaqueCube() { + return false; + } + + @Override + public boolean canRenderInPass(int a) { + return true; + } + + @Override + public boolean renderAsNormalBlock() { + return false; + } + + @Override + public boolean hasTileEntity(int metadata) { + return true; + } + + @Override + public TileEntity createTileEntity(World world, int metadata) { + return new TileWormhole(); + } + + @Override + public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int meta, int fortune) { + return new ArrayList<>(); + } + + @Override + public boolean isCollidable() { + return true; + } + +} diff --git a/src/main/java/gregtech/common/render/GT_WormholeRenderer.java b/src/main/java/gregtech/common/render/GT_WormholeRenderer.java new file mode 100644 index 0000000000..43385eb861 --- /dev/null +++ b/src/main/java/gregtech/common/render/GT_WormholeRenderer.java @@ -0,0 +1,79 @@ +package gregtech.common.render; + +import static com.github.technus.tectech.rendering.EOH.EOH_RenderingUtils.addRenderedBlockInWorld; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.init.Blocks; +import net.minecraft.tileentity.TileEntity; + +import org.lwjgl.opengl.GL11; + +import cpw.mods.fml.client.registry.ClientRegistry; +import gregtech.common.tileentities.render.TileWormhole; + +public class GT_WormholeRenderer extends TileEntitySpecialRenderer { + + public GT_WormholeRenderer() { + ClientRegistry.bindTileEntitySpecialRenderer(TileWormhole.class, this); + } + + private static final double trimPercentage = .95; + private static final double corePercentage = trimPercentage / Math.sqrt(3); + + private static void render(Block coreBlock, double rotation) { + + GL11.glPushMatrix(); + GL11.glRotated(rotation, 2, 1, 0); + GL11.glScaled(-1, -1, -1); + + Tessellator.instance.startDrawingQuads(); + Tessellator.instance.setColorOpaque_F(1f, 1f, 1f); + addRenderedBlockInWorld(Blocks.quartz_block, 0, 0, 0, 0); + Tessellator.instance.draw(); + + GL11.glScaled(trimPercentage, trimPercentage, trimPercentage); + + Tessellator.instance.startDrawingQuads(); + Tessellator.instance.setColorOpaque_F(0.1f, 0.1f, 0.1f); + addRenderedBlockInWorld(Blocks.coal_block, 0, 0, 0, 0); + Tessellator.instance.draw(); + GL11.glPopMatrix(); + + if (coreBlock != null) { + GL11.glPushMatrix(); + GL11.glScaled(corePercentage, corePercentage, corePercentage); + GL11.glRotated(rotation, 0, -2, .1); + Tessellator.instance.startDrawingQuads(); + Tessellator.instance.setColorOpaque_F(1f, 1f, 1f); + addRenderedBlockInWorld(coreBlock, 0, 0, 0, 0); + Tessellator.instance.draw(); + GL11.glPopMatrix(); + } + + } + + @Override + public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float timeSinceLastTick) { + + if (tile instanceof TileWormhole wTile) { + GL11.glPushMatrix(); + GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5); + GL11.glScaled(wTile.targetRadius, wTile.targetRadius, wTile.targetRadius); + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); + GL11.glDisable(GL11.GL_LIGHTING); + + double rotationTimer = wTile.getWorldObj() + .getWorldInfo() + .getWorldTotalTime() + timeSinceLastTick; + + this.bindTexture(TextureMap.locationBlocksTexture); + render(wTile.getBlock(), rotationTimer); + + GL11.glPopAttrib(); + GL11.glPopMatrix(); + } + } +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_WormholeGenerator.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_WormholeGenerator.java new file mode 100644 index 0000000000..d0c356e4fe --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_WormholeGenerator.java @@ -0,0 +1,1119 @@ +package gregtech.common.tileentities.machines.multi; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.withChannel; +import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO; +import static gregtech.api.enums.GT_HatchElement.InputBus; +import static gregtech.api.enums.GT_HatchElement.Maintenance; +import static gregtech.api.enums.GT_Values.V; +import static gregtech.api.enums.GT_Values.VN; +import static gregtech.api.enums.Textures.BlockIcons.getCasingTextureForId; +import static gregtech.api.util.GT_StructureUtility.buildHatchAdder; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +import com.github.bartimaeusnek.bartworks.API.BorosilicateGlass; +import com.github.technus.tectech.thing.casing.GT_Block_CasingsTT; +import com.github.technus.tectech.thing.casing.TT_Container_Casings; +import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_DynamoMulti; +import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_EnergyMulti; +import com.google.common.collect.MapMaker; +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 com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; + +import appeng.api.AEApi; +import gregtech.GT_Mod; +import gregtech.api.GregTech_API; +import gregtech.api.enums.SoundResource; +import gregtech.api.enums.TierEU; +import gregtech.api.interfaces.IHatchElement; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.interfaces.tileentity.IHasWorldObjectAndCoords; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase; +import gregtech.api.recipe.check.CheckRecipeResult; +import gregtech.api.recipe.check.ResultMissingItem; +import gregtech.api.recipe.check.SimpleCheckRecipeResult; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GT_Multiblock_Tooltip_Builder; +import gregtech.api.util.IGT_HatchAdder; +import gregtech.common.tileentities.render.TileWormhole; +import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock; + +public class GT_MetaTileEntity_WormholeGenerator extends + GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_WormholeGenerator> implements ISurvivalConstructable { + + /** + * Number of seconds to average the wormhole energy over. + */ + public static int WH_ENERGY_AVG_WINDOW = 90; + + /** + * The amount of EU received per EU sent. + */ + public static double TRANSFER_EFFICIENCY = (1.0 - 0.00_0004 * 64); + + /** + * The amount of EU to lose every second the wormhole decays. + */ + public static double DECAY_RATE = 0.25; + + /** + * The amount of EU that the wormhole collapses at. + */ + public static double COLLAPSE_THRESHOLD = 32; + + /** + * The wormhole render radius percent of the max size when specified wormhole power is reached (purely aesthetical) + */ + public static double RENDER_PERCENT_TARGET = .1; + + /** + * Wormhole energy to specify reach the specified size percentage (purely aesthetical) + */ + public static double RENDER_TARGET_ENERGY = TierEU.IV * 256; + + /** + * Maximum wormhole radius (purely aesthetical) + */ + public static double RENDER_MAX_RADIUS = 2.999 / Math.sqrt(3); + + private static final String STRUCTURE_PIECE_MAIN = "main"; + private static final byte GLASS_TIER_UNSET = -2; + + private static final int TT_CASING_INDEX = GT_Block_CasingsTT.textureOffset; + + private static final int TOP_HATCH = 0, BOTTOM_HATCH = 1, LEFT_HATCH = 2, RIGHT_HATCH = 3, BACK_HATCH = 4, + FRONT_HATCH = 5, MAX_HATCHES = 6; + + private static final int[] OPPOSITES = { BOTTOM_HATCH, TOP_HATCH, RIGHT_HATCH, LEFT_HATCH, FRONT_HATCH, + BACK_HATCH, }; + + private static final String[] HATCH_NAMES = { "Top", "Bottom", "Left", "Right", "Back", "Front" }; + private static final boolean[] HATCH_MASK = { true, true, true, true, false, false }; + + private byte mGlassTier = -2; + private boolean mStructureBadGlassTier = false; + + private final GT_MetaTileEntity_Hatch_EnergyMulti[] mSendHatches = new GT_MetaTileEntity_Hatch_EnergyMulti[MAX_HATCHES]; + private final GT_MetaTileEntity_Hatch_DynamoMulti[] mReceiveHatches = new GT_MetaTileEntity_Hatch_DynamoMulti[MAX_HATCHES]; + + private final ItemStack singularity = AEApi.instance() + .definitions() + .materials() + .singularity() + .maybeStack(1) + .get(); + private final ItemStack qeSingularity = AEApi.instance() + .definitions() + .materials() + .qESingularity() + .maybeStack(1) + .get(); + + private WormholeLink mLink; + private final WeakReference<GT_MetaTileEntity_WormholeGenerator> mSelfReference = new WeakReference<>(this); + + private double mWormholeEnergy_UI = 0; + + private boolean mIsUnloading = false; + + public GT_MetaTileEntity_WormholeGenerator(int aID, String aName, String aNameRegional) { + super(aID, aName, aNameRegional); + } + + public GT_MetaTileEntity_WormholeGenerator(String aName) { + super(aName); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new GT_MetaTileEntity_WormholeGenerator(mName); + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int colorIndex, boolean active, boolean redstoneLevel) { + if (side == facing) { + if (active) { + return new ITexture[] { getCasingTextureForId(TT_CASING_INDEX), TextureFactory.builder() + .addIcon(TexturesGtBlock.Overlay_Machine_Controller_Advanced_Active) + .extFacing() + .build() }; + } else { + return new ITexture[] { getCasingTextureForId(TT_CASING_INDEX), TextureFactory.builder() + .addIcon(TexturesGtBlock.Overlay_Machine_Controller_Advanced) + .extFacing() + .build() }; + } + } + return new ITexture[] { getCasingTextureForId(TT_CASING_INDEX) }; + } + + // #region Structure + + // spotless:off + private static final IStructureDefinition<GT_MetaTileEntity_WormholeGenerator> STRUCTURE_DEFINITION = StructureDefinition + .<GT_MetaTileEntity_WormholeGenerator>builder() + .addShape( + STRUCTURE_PIECE_MAIN, + transpose( + new String[][]{ + {" "," F "," EEE "," FEtEF "," EEE "," F "," "}, + {" F "," AADAA "," A B A ","FDBBBDF"," A B A "," AADAA "," F "}, + {" EEE "," A B A ","E E","EB BE","E E"," A B A "," EEE "}, + {" FE~EF ","FA B AF","E E","lB Br","E E","FA B AF"," FEEEF "}, + {" EEE "," A B A ","E E","EB BE","E E"," A B A "," EEE "}, + {" F "," AADAA "," A B A ","FDBBBDF"," A B A "," AADAA "," F "}, + {" "," F "," EEE "," FEbEF "," EEE "," F "," "} + })) + .addElement('E', + buildHatchAdder(GT_MetaTileEntity_WormholeGenerator.class) + .atLeast(Maintenance, InputBus) + .casingIndex(TT_CASING_INDEX) // High Power Casing + .dot(1) + .buildAndChain(lazy(() -> ofBlock(TT_Container_Casings.sBlockCasingsTT, 0))) // High Power Casing + ) + .addElement( + 'A', + withChannel( + "glass", + BorosilicateGlass.ofBoroGlass(GLASS_TIER_UNSET, (te, t) -> te.mGlassTier = t, te -> te.mGlassTier)) + ) + .addElement('D', ofBlock(GregTech_API.sBlockCasings8, 5)) // Europium Reinforced Radiation Proof Machine Casing + .addElement('B', ofBlock(GregTech_API.sBlockCasings4, 7)) // Fusion Coil Block + .addElement('F', lazy(() -> ofBlock(TT_Container_Casings.sBlockCasingsTT, 4))) // Molecular Casing + .addElement('t', + buildHatchAdder(GT_MetaTileEntity_WormholeGenerator.class) + .anyOf(new TransferHatch(TOP_HATCH)) + .casingIndex(TT_CASING_INDEX) // High Power Casing + .dot(2) + .buildAndChain(lazy(() -> ofBlock(TT_Container_Casings.sBlockCasingsTT, 0))) // High Power Casing + ) + .addElement('b', + buildHatchAdder(GT_MetaTileEntity_WormholeGenerator.class) + .anyOf(new TransferHatch(BOTTOM_HATCH)) + .casingIndex(TT_CASING_INDEX) // High Power Casing + .dot(2) + .buildAndChain(lazy(() -> ofBlock(TT_Container_Casings.sBlockCasingsTT, 0))) // High Power Casing + ) + .addElement('l', + buildHatchAdder(GT_MetaTileEntity_WormholeGenerator.class) + .anyOf(new TransferHatch(LEFT_HATCH)) + .casingIndex(TT_CASING_INDEX) // High Power Casing + .dot(2) + .buildAndChain(lazy(() -> ofBlock(TT_Container_Casings.sBlockCasingsTT, 0))) // High Power Casing + ) + .addElement('r', + buildHatchAdder(GT_MetaTileEntity_WormholeGenerator.class) + .anyOf(new TransferHatch(RIGHT_HATCH)) + .casingIndex(TT_CASING_INDEX) // High Power Casing + .dot(2) + .buildAndChain(lazy(() -> ofBlock(TT_Container_Casings.sBlockCasingsTT, 0))) // High Power Casing + ) + .build(); + // spotless:on + + private static class TransferHatch implements IHatchElement<GT_MetaTileEntity_WormholeGenerator> { + + public final int mIndex; + + public TransferHatch(int index) { + this.mIndex = index; + } + + @Override + public List<? extends Class<? extends IMetaTileEntity>> mteClasses() { + return Arrays.asList(GT_MetaTileEntity_Hatch_EnergyMulti.class, GT_MetaTileEntity_Hatch_DynamoMulti.class); + } + + @Override + public IGT_HatchAdder<? super GT_MetaTileEntity_WormholeGenerator> adder() { + return (tile, aTileEntity, aBaseCasingIndex) -> { + if (aTileEntity == null) return false; + + IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity(); + + if (aMetaTileEntity == null) return false; + + if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_EnergyMulti input) { + input.updateTexture(aBaseCasingIndex); + input.updateCraftingIcon(tile.getMachineCraftingIcon()); + tile.mSendHatches[mIndex] = input; + return true; + } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_DynamoMulti output) { + output.updateTexture(aBaseCasingIndex); + output.updateCraftingIcon(tile.getMachineCraftingIcon()); + tile.mReceiveHatches[mIndex] = output; + return true; + } + + return false; + }; + } + + @Override + public String name() { + return "TransferHatch"; + } + + @Override + public long count(GT_MetaTileEntity_WormholeGenerator t) { + return t.mExoticEnergyHatches.size(); + } + } + + @Override + public boolean isCorrectMachinePart(ItemStack aStack) { + return true; + } + + @Override + protected SoundResource getProcessStartSound() { + return SoundResource.GT_MACHINES_FUSION_LOOP; + } + + @Override + public IStructureDefinition<GT_MetaTileEntity_WormholeGenerator> getStructureDefinition() { + return STRUCTURE_DEFINITION; + } + + @Override + public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { + if (!checkPiece(STRUCTURE_PIECE_MAIN, 3, 3, 0)) return false; + + mStructureBadGlassTier = false; + + for (var energyHatch : mExoticEnergyHatches) { + if (energyHatch.getBaseMetaTileEntity() == null) { + continue; + } + + if (energyHatch.getTierForStructure() > mGlassTier) { + mStructureBadGlassTier = true; + } + } + + return !mStructureBadGlassTier; + } + + @Override + public void clearHatches() { + super.clearHatches(); + + Arrays.fill(mSendHatches, null); + Arrays.fill(mReceiveHatches, null); + } + + @Override + public void construct(ItemStack stackSize, boolean hintsOnly) { + buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 3, 3, 0); + } + + @Override + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + if (mMachine) return -1; + return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 3, 3, 0, elementBudget, env, false, true); + } + + @Override + public int getDamageToComponent(ItemStack aStack) { + return 0; + } + + @Override + public boolean explodesOnComponentBreak(ItemStack aStack) { + return false; + } + + // #endregion + @Override + public void onBlockDestroyed() { + super.onBlockDestroyed(); + destroyRenderBlock(); + } + + @Override + public void onDisableWorking() { + super.onDisableWorking(); + // destroyRenderBlock(); + } + + @Override + public void onStructureChange() { + super.onStructureChange(); + if (!checkStructure(false, this.getBaseMetaTileEntity())) { + destroyRenderBlock(); + } + } + + private void destroyRenderBlock() { + IGregTechTileEntity gregTechTileEntity = this.getBaseMetaTileEntity(); + if (gregTechTileEntity.getWorld() == null) { + return; + } + + int x = gregTechTileEntity.getXCoord(); + int y = gregTechTileEntity.getYCoord(); + int z = gregTechTileEntity.getZCoord(); + + int xOffset = 3 * getExtendedFacing().getRelativeBackInWorld().offsetX; + int yOffset = 3 * getExtendedFacing().getRelativeBackInWorld().offsetY; + int zOffset = 3 * getExtendedFacing().getRelativeBackInWorld().offsetZ; + + int xTarget = x + xOffset; + int yTarget = y + yOffset; + int zTarget = z + zOffset; + + Optional.of(gregTechTileEntity) + .map(IHasWorldObjectAndCoords::getWorld) + .ifPresent(w -> w.setBlock(xTarget, yTarget, zTarget, Blocks.air)); + } + + @Nullable + private TileWormhole createRenderBlock() { + + IGregTechTileEntity gregTechTileEntity = this.getBaseMetaTileEntity(); + World world = gregTechTileEntity.getWorld(); + + if (world == null) { + return null; + } + + int x = gregTechTileEntity.getXCoord(); + int y = gregTechTileEntity.getYCoord(); + int z = gregTechTileEntity.getZCoord(); + + int xOffset = 3 * getExtendedFacing().getRelativeBackInWorld().offsetX; + int yOffset = 3 * getExtendedFacing().getRelativeBackInWorld().offsetY; + int zOffset = 3 * getExtendedFacing().getRelativeBackInWorld().offsetZ; + + int xTarget = x + xOffset; + int yTarget = y + yOffset; + int zTarget = z + zOffset; + + world.setBlock(xTarget, yTarget, zTarget, Blocks.air); + world.setBlock(xTarget, yTarget, zTarget, GregTech_API.sWormholeRender); + + TileWormhole wormhole = (TileWormhole) world.getTileEntity(xTarget, yTarget, zTarget); + + if (wormhole == null) { + return null; + } + return wormhole; + } + + @Nullable + private TileWormhole getRenderBlock() { + IGregTechTileEntity gregTechTileEntity = this.getBaseMetaTileEntity(); + + int x = gregTechTileEntity.getXCoord(); + int y = gregTechTileEntity.getYCoord(); + int z = gregTechTileEntity.getZCoord(); + + double xOffset = 3 * getExtendedFacing().getRelativeBackInWorld().offsetX; + double zOffset = 3 * getExtendedFacing().getRelativeBackInWorld().offsetZ; + double yOffset = 3 * getExtendedFacing().getRelativeBackInWorld().offsetY; + + int wX = (int) (x + xOffset); + int wY = (int) (y + yOffset); + int wZ = (int) (z + zOffset); + + TileEntity tile = Optional.ofNullable(gregTechTileEntity.getWorld()) + .map(w -> w.getTileEntity(wX, wY, wZ)) + .orElse(null); + if (tile instanceof TileWormhole wormhole) return wormhole; + return null; + + } + + public void updateRenderDim() { + TileWormhole temp = getRenderBlock(); + + World target = Optional.ofNullable(mLink) + .map(link -> link.getDest(mSelfReference)) + .map(MetaTileEntity::getBaseMetaTileEntity) + .map(IHasWorldObjectAndCoords::getWorld) + .orElse(null); + + TileWormhole hole = getRenderBlock(); + if (hole == null) hole = createRenderBlock(); + + if (hole != null) { + hole.setDimFromWorld(target); + } + } + + public void updateRenderRadius(double radius) { + TileWormhole hole = getRenderBlock(); + if (hole == null) hole = createRenderBlock(); + + if (hole != null) { + hole.setRadius(radius); + } + } + + private static double wormholeRadiusCalc(double energy) { + if (energy < COLLAPSE_THRESHOLD) return 0; + + double offset = RENDER_TARGET_ENERGY + (COLLAPSE_THRESHOLD - RENDER_TARGET_ENERGY) / (RENDER_PERCENT_TARGET); + return RENDER_MAX_RADIUS * (COLLAPSE_THRESHOLD - energy) / (offset - energy); + } + + // #region Logic + + @Override + public int getMaxEfficiency(ItemStack aStack) { + return 10000; + } + + @Override + public void onUnload() { + super.onUnload(); + mIsUnloading = true; + if (mLink != null) { + mLink.disconnect(mSelfReference); + } + } + + @Override + protected void runMachine(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + checkFrequency(); + + mMaxProgresstime = 20; + mEfficiency = Math.max(0, getMaxEfficiency(mInventory[1]) - ((getIdealStatus() - getRepairStatus()) * 1000)); + + if (doRandomMaintenanceDamage()) { + if (onRunningTick(mInventory[1])) { + markDirty(); + + if (++mProgresstime >= mMaxProgresstime) { + mProgresstime = 0; + + if (mLink != null) { + mLink.update(mSelfReference); + } + checkRecipe(); + } + } + } + } + + @Override + @Nonnull + public CheckRecipeResult checkProcessing() { + if (mLink == null || !mLink.isConnected(mSelfReference) + || getBaseMetaTileEntity() == null + || !getBaseMetaTileEntity().isAllowedToWork()) { + return SimpleCheckRecipeResult.ofFailure("none"); + } + + if (mLink.isActive()) { + for (int i = 0; i < MAX_HATCHES; i++) { + if (!HATCH_MASK[i]) continue; + + long optimal = mLink.mWormholeEnergy > Long.MAX_VALUE ? Long.MAX_VALUE : ((long) mLink.mWormholeEnergy); + if (getTransferable(i) > 0) { + if (mLink.mWormholeEnergy <= 0) { + var singularityStack = singularity.copy(); + + if (!depleteInput(singularityStack)) { + return new ResultMissingItem(singularityStack); + } + mLink.mWormholeEnergy = 1; + optimal = 1; + } + transferPower(optimal, i); + } + } + } + + if (mLink.mWormholeEnergy > 0) { + return SimpleCheckRecipeResult.ofSuccess("none"); + } + return SimpleCheckRecipeResult.ofFailure("none"); + } + + private void checkFrequency() { + if (mIsUnloading) { + return; + } + + ItemStack link = null; + + for (var slot : mInventory) { + if (slot != null && qeSingularity.getItem() == slot.getItem() + && qeSingularity.getItemDamage() == slot.getItemDamage()) { + link = slot; + break; + } + } + + Long freq = link != null && link.getTagCompound() != null + && link.getTagCompound() + .hasKey("freq", 4 /* Long */) ? link.getTagCompound() + .getLong("freq") : null; + + if (!Objects.equals(freq, mLink == null ? null : mLink.mFrequency)) { + if (mLink != null) { + mLink.disconnect(mSelfReference); + mLink = null; + } + + if (freq != null) { + mLink = WormholeLink.get(freq); + mLink.connect(mSelfReference); + } + } + } + + private long getTransferable(int index) { + var dest = mLink.getDest(mSelfReference); + if (dest == null || mMaxProgresstime == 0 || dest.mMaxProgresstime == 0) { + return 0; + } + + var inputHatch = mSendHatches[index]; + var outputHatch = dest.mReceiveHatches[OPPOSITES[index]]; + + if (inputHatch == null || outputHatch == null) { + return 0; + } + + long available = inputHatch.getEUVar(); + long empty = outputHatch.maxEUStore() - outputHatch.getEUVar(); + + return Math.min(available, empty); + } + + private void transferPower(long optimal, int index) { + var dest = mLink.getDest(mSelfReference); + if (dest == null) { + return; + } + + var inputHatch = mSendHatches[index]; + var outputHatch = dest.mReceiveHatches[OPPOSITES[index]]; + + if (inputHatch == null || outputHatch == null) { + return; + } + + long available = inputHatch.getEUVar(); + long empty = outputHatch.maxEUStore() - outputHatch.getEUVar(); + long maxSend = inputHatch.maxAmperesIn() * V[inputHatch.mTier] * 20; + long maxReceive = outputHatch.maxAmperesOut() * V[outputHatch.mTier] * 20; + + // spotless:off + long toSend = (long)(Math.min(Math.min(Math.min(available, empty), maxSend), maxReceive) * (1.0 - (getIdealStatus() - getRepairStatus()) * 0.1)); + + double overclocks = Math.max(Math.log((double)toSend / (double)optimal) / Math.log(4.0), 0.0); + + long toReceive = (long) ( + toSend * + (1.0 / Math.pow(4.0, overclocks)) * + Math.pow(2.0, overclocks) * + (1.0 - (dest.getIdealStatus() - dest.getRepairStatus()) * 0.1) * + TRANSFER_EFFICIENCY + ); + // spotless:on + + inputHatch.setEUVar(inputHatch.getEUVar() - toSend); + outputHatch.setEUVar(outputHatch.getEUVar() + toReceive); + + double size = wormholeRadiusCalc((double) optimal / 20); + this.updateRenderRadius(size); + dest.updateRenderRadius(size); + + mLink.onEnergyTransferred(toSend); + mLink.mSendAmounts[index] += toSend; + mLink.mReceiveAmounts[OPPOSITES[index]] += toReceive; + } + + @Override + public void saveNBTData(NBTTagCompound aNBT) { + super.saveNBTData(aNBT); + + try { + if (mLink != null) { + mLink.tryPromote(); + + NBTTagCompound link = new NBTTagCompound(); + + link.setLong("mFrequency", mLink.mFrequency); + link.setDouble("mWormholeEnergy", mLink.mWormholeEnergy); + + if (mLink.isMaster(mSelfReference)) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + dos.writeInt(mLink.mReceiveAmounts.length); + for (var x : mLink.mReceiveAmounts) { + dos.writeLong(x); + } + + dos.writeInt(mLink.mSendAmounts.length); + for (var x : mLink.mSendAmounts) { + dos.writeLong(x); + } + + link.setByteArray("data", baos.toByteArray()); + } + + aNBT.setTag("mLink", link); + } + } catch (Throwable t) { + GT_Mod.GT_FML_LOGGER.error("Could not save GT_MetaTileEntity_WormholeGenerator", t); + } + + } + + @Override + public void loadNBTData(NBTTagCompound aNBT) { + super.loadNBTData(aNBT); + + checkFrequency(); + + if (aNBT.hasKey("mLink") && mLink != null) { + NBTTagCompound link = aNBT.getCompoundTag("mLink"); + + long freq = link.getLong("mFrequency"); + + try { + if (freq == mLink.mFrequency && mLink.isMaster(mSelfReference)) { + mLink.mWormholeEnergy = link.getDouble("mWormholeEnergy"); + + ByteArrayInputStream bais = new ByteArrayInputStream(link.getByteArray("data")); + DataInputStream dis = new DataInputStream(bais); + + long[] recv_amounts = new long[dis.readInt()]; + for (int i = 0; i < recv_amounts.length; i++) { + recv_amounts[i] = dis.readLong(); + } + + System.arraycopy( + recv_amounts, + 0, + mLink.mReceiveAmounts, + 0, + Math.min(recv_amounts.length, mLink.mReceiveAmounts.length)); + + long[] send_amounts = new long[dis.readInt()]; + for (int i = 0; i < send_amounts.length; i++) { + send_amounts[i] = dis.readLong(); + } + + System.arraycopy( + send_amounts, + 0, + mLink.mSendAmounts, + 0, + Math.min(send_amounts.length, mLink.mSendAmounts.length)); + } + } catch (Throwable t) { + GT_Mod.GT_FML_LOGGER.error("Could not load GT_MetaTileEntity_WormholeGenerator", t); + } + } + } + + private static class WormholeLink { + + private final static Map<Long, WormholeLink> WORMHOLE_GENERATORS = new MapMaker().weakValues() + .makeMap(); + + public final long mFrequency; + + public WeakReference<GT_MetaTileEntity_WormholeGenerator> mMaster, mSlave; + + public final long[] mSendAmounts = new long[MAX_HATCHES]; + public final long[] mReceiveAmounts = new long[MAX_HATCHES]; + + public double mWormholeEnergy; + private double mPendingEnergy; + + private WormholeLink(long frequency) { + mFrequency = frequency; + } + + public static WormholeLink get(long frequency) { + return WORMHOLE_GENERATORS.computeIfAbsent(frequency, WormholeLink::new); |
