aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common/tileentities/machines
diff options
context:
space:
mode:
authorRealSilverMoon <31100241+RealSilverMoon@users.noreply.github.com>2024-02-01 01:15:29 +0800
committerGitHub <noreply@github.com>2024-01-31 18:15:29 +0100
commit787eba0a15c583b240e96630978b9c3539e55fa4 (patch)
treed4a4ba4e4fb4ea9d09174215581da5c79a6413a2 /src/main/java/gregtech/common/tileentities/machines
parent19950f533392fdadc5858ba12adce64374414083 (diff)
downloadGT5-Unofficial-787eba0a15c583b240e96630978b9c3539e55fa4.tar.gz
GT5-Unofficial-787eba0a15c583b240e96630978b9c3539e55fa4.tar.bz2
GT5-Unofficial-787eba0a15c583b240e96630978b9c3539e55fa4.zip
Add Drone Centre (#2412)
* Add Drone Centre * Apply texture and model * Update en_US.lang * Remove import.* * Switch to block render * Balance range and break chance * Add recipe * Spotless * Update lang * Fix recipe * Rewrite connection system and UI * Remove debuff party * Spotless * Fix server class not found * A stupid enough recipe * Another bad recipe * Update tooltip & i18n * Close it! * Spotless * Disable draggable * prohibited remote control when centre is offline * Rename * Rename; Change specifiers * Update texture * spotless --------- Co-authored-by: Martin Robertz <dream-master@gmx.net>
Diffstat (limited to 'src/main/java/gregtech/common/tileentities/machines')
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/drone/DroneConnection.java123
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_DroneCentre.java666
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_Hatch_DroneDownLink.java269
3 files changed, 1058 insertions, 0 deletions
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/drone/DroneConnection.java b/src/main/java/gregtech/common/tileentities/machines/multi/drone/DroneConnection.java
new file mode 100644
index 0000000000..57a8bea352
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/drone/DroneConnection.java
@@ -0,0 +1,123 @@
+package gregtech.common.tileentities.machines.multi.drone;
+
+import static gregtech.GT_Mod.gregtechproxy;
+
+import java.util.Optional;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.world.World;
+import net.minecraftforge.common.DimensionManager;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.IHasWorldObjectAndCoords;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.util.GT_Util;
+
+public class DroneConnection {
+
+ String customName;
+ GT_MetaTileEntity_MultiBlockBase machine;
+ ItemStack machineItem;
+ ChunkCoordinates machineCoord;
+ GT_MetaTileEntity_DroneCentre centre;
+ ChunkCoordinates centreCoord;
+ World world;
+
+ public DroneConnection(GT_MetaTileEntity_MultiBlockBase machine, GT_MetaTileEntity_DroneCentre centre) {
+ this.machine = machine;
+ this.machineItem = machine.getStackForm(1);
+ machineCoord = machine.getBaseMetaTileEntity()
+ .getCoords();
+ this.centre = centre;
+ centreCoord = centre.getBaseMetaTileEntity()
+ .getCoords();
+ this.world = centre.getBaseMetaTileEntity()
+ .getWorld();
+ customName = Optional.ofNullable(centre.tempNameList.remove(machineCoord.toString()))
+ .orElse(machine.getLocalName());
+ }
+
+ public DroneConnection(NBTTagCompound aNBT) {
+ NBTTagCompound machineTag = aNBT.getCompoundTag("machine");
+ NBTTagCompound centreTag = aNBT.getCompoundTag("centre");
+ if (!gregtechproxy.isClientSide()) {
+ this.world = DimensionManager.getWorld(aNBT.getInteger("worldID"));
+ } else {
+ this.world = Minecraft.getMinecraft().thePlayer.worldObj;
+ }
+ machineItem = ItemStack.loadItemStackFromNBT(aNBT.getCompoundTag("item"));
+ machineCoord = new ChunkCoordinates(
+ machineTag.getInteger("x"),
+ machineTag.getInteger("y"),
+ machineTag.getInteger("z"));
+ this.machine = getLoadedGT_BaseMachineAt(machineCoord, world, true);
+ centreCoord = new ChunkCoordinates(
+ centreTag.getInteger("x"),
+ centreTag.getInteger("y"),
+ centreTag.getInteger("z"));
+ this.centre = (GT_MetaTileEntity_DroneCentre) getLoadedGT_BaseMachineAt(centreCoord, world, true);
+ this.customName = aNBT.getString("name");
+ }
+
+ public GT_MetaTileEntity_MultiBlockBase getMachine() {
+ return machine;
+ }
+
+ public boolean reCheckConnection() {
+ if (machine == null) this.machine = getLoadedGT_BaseMachineAt(machineCoord, world, true);
+ if (centre == null)
+ this.centre = (GT_MetaTileEntity_DroneCentre) getLoadedGT_BaseMachineAt(centreCoord, world, true);
+ if (machine != null && centre != null
+ && !centre.getConnectionList()
+ .contains(this))
+ centre.getConnectionList()
+ .add(this);
+ return isValid();
+ }
+
+ public String getCustomName() {
+ return customName;
+ }
+
+ public void setCustomName(String name) {
+ customName = name;
+ }
+
+ public NBTTagCompound transConnectionToNBT() {
+ NBTTagCompound aNBT = new NBTTagCompound();
+ if (!this.isValid()) return aNBT;
+ aNBT.setTag("machine", transGT_BaseMachineToNBT(machine));
+ aNBT.setTag("centre", transGT_BaseMachineToNBT(centre));
+ aNBT.setTag("item", machineItem.writeToNBT(new NBTTagCompound()));
+ aNBT.setInteger(
+ "worldID",
+ machine.getBaseMetaTileEntity()
+ .getWorld().provider.dimensionId);
+ aNBT.setString("name", getCustomName());
+ return aNBT;
+ }
+
+ public GT_MetaTileEntity_MultiBlockBase getLoadedGT_BaseMachineAt(ChunkCoordinates coords, World world,
+ boolean isLoaded) {
+ TileEntity te = GT_Util.getTileEntity(world, coords, isLoaded);
+ if (te == null) return null;
+ return (GT_MetaTileEntity_MultiBlockBase) ((IGregTechTileEntity) te).getMetaTileEntity();
+ }
+
+ private NBTTagCompound transGT_BaseMachineToNBT(GT_MetaTileEntity_MultiBlockBase machine) {
+ IHasWorldObjectAndCoords baseCoord = machine.getBaseMetaTileEntity();
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setInteger("x", baseCoord.getXCoord());
+ tag.setInteger("y", baseCoord.getYCoord());
+ tag.setInteger("z", baseCoord.getZCoord());
+ return tag;
+ }
+
+ public boolean isValid() {
+ return machine != null && machine.isValid() && centre != null && centre.isValid();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_DroneCentre.java b/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_DroneCentre.java
new file mode 100644
index 0000000000..ee4ea4978d
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_DroneCentre.java
@@ -0,0 +1,666 @@
+package gregtech.common.tileentities.machines.multi.drone;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_Values.AuthorSilverMoon;
+import static gregtech.api.multitileentity.multiblock.casing.Glasses.chainAllGlasses;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.HashMultimap;
+import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
+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.gtnewhorizon.structurelib.util.Vec3Impl;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+import com.gtnewhorizons.modularui.api.forge.ItemStackHandler;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.api.math.MainAxisAlignment;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedRow;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.Scrollable;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget;
+
+import appeng.api.util.DimensionalCoord;
+import appeng.api.util.WorldCoord;
+import appeng.client.render.BlockPosHighlighter;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.items.GT_TierDrone;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_DroneCentre extends
+ GT_MetaTileEntity_ExtendedPowerMultiBlockBase<GT_MetaTileEntity_DroneCentre> implements ISurvivalConstructable {
+
+ private static final IIconContainer ACTIVE = new Textures.BlockIcons.CustomIcon("iconsets/DRONE_CENTRE_ACTIVE");
+ private static final IIconContainer FACE = new Textures.BlockIcons.CustomIcon("iconsets/DRONE_CENTRE_FACE");
+ private static final IIconContainer INACTIVE = new Textures.BlockIcons.CustomIcon("iconsets/DRONE_CENTRE_INACTIVE");
+ private Vec3Impl centreCoord;
+ private int droneLevel = 0;
+ private int buttonID;
+ private final List<DroneConnection> connectionList = new ArrayList<>();
+ public HashMap<String, String> tempNameList = new HashMap<>();
+ // Save centre by dimID
+ private static final HashMultimap<Integer, GT_MetaTileEntity_DroneCentre> droneMap = HashMultimap.create();
+ // spotless off
+ private static final IStructureDefinition<GT_MetaTileEntity_DroneCentre> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_DroneCentre>builder()
+ .addShape(
+ "main",
+ transpose(
+ new String[][] { { " ", " ", " ", " ", "CCCCC", "CCCCC", "CCCCC", "CCCCC", "CCCCC" },
+ { "CE~EC", "C C", "C C", "C C", "CAAAC", "CCCCC", "CAAAC", "C C", "CCCCC" },
+ { "CEEEC", "CBBBC", "CBDBC", "CBBBC", "CCCCC", "CCCCC", "CCCCC", "CCCCC", "CCCCC" },
+ { "C C", " ", " ", " ", " ", " ", " ", " ", "C C" },
+ { "C C", " ", " ", " ", " ", " ", " ", " ", "C C" },
+ { "C C", " ", " ", " ", " ", " ", " ", " ", "C C" } }))
+ .addElement(
+ 'E',
+ buildHatchAdder(GT_MetaTileEntity_DroneCentre.class).atLeast(InputBus)
+ .casingIndex(59)
+ .dot(1)
+ .buildAndChain(ofBlock(GregTech_API.sBlockCasings4, 2)))
+ .addElement('C', ofBlock(GregTech_API.sBlockCasings4, 2))
+ .addElement('A', chainAllGlasses())
+ .addElement('B', ofBlock(GregTech_API.sBlockCasings1, 11))
+ .addElement('D', ofBlock(GregTech_API.sBlockCasings4, 0))
+ .build();
+
+ // spotless on
+ public GT_MetaTileEntity_DroneCentre(String name) {
+ super(name);
+ }
+
+ public GT_MetaTileEntity_DroneCentre(int ID, String Name, String NameRegional) {
+ super(ID, Name, NameRegional);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_DroneCentre(super.mName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (getBaseMetaTileEntity().isActive()) {
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(59), TextureFactory.builder()
+ .addIcon(ACTIVE)
+ .extFacing()
+ .build() };
+ } else {
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(59), TextureFactory.builder()
+ .addIcon(INACTIVE)
+ .extFacing()
+ .build() };
+ }
+ } else if (side == aFacing.getOpposite()) {
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(59), TextureFactory.builder()
+ .addIcon(FACE)
+ .extFacing()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(59) };
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_DroneCentre> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Drone Centre")
+ .addInfo("Drone Center Controller")
+ .addInfo(EnumChatFormatting.AQUA + "Drone #10032, cleared for takeoff!")
+ .addInfo("Monitors multiblock machines in range.")
+ .addInfo("Replace maintenance hatch on other multi with drone downlink module.")
+ .addInfo("Provides maintenance, power control, monitoring and etc.")
+ .addInfo("Range is determined by drone tier: T1-32, T2-128, T3-512")
+ .addInfo("Place drones in input bus; only one needed to operate.")
+ .addInfo("Automatically upgrade based on the drone level in the input bus.")
+ .addInfo("There is a chance per second that the drone will crash.")
+ .addInfo("Chance is determined by drone tier: T1-1/28800, T2-1/172800, T3-0")
+ .addInfo("If machine is too far, remote control would not available")
+ .addInfo(AuthorSilverMoon)
+ .addSeparator()
+ .beginStructureBlock(5, 6, 9, false)
+ .addStructureInfo("Do not need maintenance hatch")
+ .addSeparator()
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece("main", stackSize, hintsOnly, 2, 1, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stack, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece("main", stack, 2, 1, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ protected IAlignmentLimits getInitialAlignmentLimits() {
+ // I don't think a drone can take off HORIZONTALLY!
+ return (d, r, f) -> (d.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0 && r.isNotRotated()
+ && !f.isVerticallyFliped();
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ return checkPiece("main", 2, 1, 0);
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ fixAll();
+ if (aTick % 200 == 0) {
+ if (switch (droneLevel) {
+ case 1 -> getBaseMetaTileEntity().getRandomNumber(28800);
+ case 2 -> getBaseMetaTileEntity().getRandomNumber(172800);
+ default -> 1;
+ } == 0) {
+ droneLevel = 0;
+ if (!tryConsumeDrone()) criticalStopMachine();
+ }
+ }
+ // Clean invalid connections every 4 seconds
+ if (aTick % 80 == 0) connectionList.removeIf(v -> !v.isValid());
+ }
+ if (mMaxProgresstime > 0 && mMaxProgresstime - mProgresstime == 1) destroyRenderBlock();
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ droneLevel = aNBT.getInteger("drone");
+ NBTTagCompound nameList = aNBT.getCompoundTag("conList");
+ for (String s : nameList.func_150296_c()) {
+ tempNameList.put(s, nameList.getString(s));
+ }
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("drone", droneLevel);
+ NBTTagCompound conList = new NBTTagCompound();
+ for (DroneConnection con : connectionList) {
+ if (!Objects.equals(con.customName, con.machine.getLocalName()))
+ conList.setString(con.machineCoord.toString(), con.customName);
+ }
+ aNBT.setTag("conList", conList);
+ }
+
+ @Override
+ public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y,
+ int z) {
+ super.getWailaNBTData(player, tile, tag, world, x, y, z);
+ tag.setInteger("connectionCount", connectionList.size());
+ if (droneLevel != 0) tag.setInteger("droneLevel", droneLevel);
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ NBTTagCompound tag = accessor.getNBTData();
+ currenttip.add(
+ EnumChatFormatting.AQUA + StatCollector.translateToLocal("GT5U.waila.drone_downlink.droneLevel")
+ + tag.getInteger("droneLevel"));
+ currenttip.add(
+ StatCollector.translateToLocal("GT5U.waila.drone_downlink.connectionCount")
+ + tag.getInteger("connectionCount"));
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (droneLevel == 0) {
+ if (!tryConsumeDrone()) return SimpleCheckRecipeResult.ofFailure("drone_noDrone");
+ }
+ if (droneLevel == 1 || droneLevel == 2) tryUpdateDrone();
+ mMaxProgresstime = 200 * droneLevel;
+ createRenderBlock();
+ return SimpleCheckRecipeResult.ofSuccess("drone_operating");
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (droneMap.containsValue(this)) return;
+ centreCoord = new Vec3Impl(
+ getBaseMetaTileEntity().getXCoord(),
+ getBaseMetaTileEntity().getYCoord(),
+ getBaseMetaTileEntity().getZCoord());
+ droneMap.put(getBaseMetaTileEntity().getWorld().provider.dimensionId, this);
+ }
+ }
+
+ @Override
+ public void onRemoval() {
+ droneMap.remove(getBaseMetaTileEntity().getWorld().provider.dimensionId, this);
+ }
+
+ public List<DroneConnection> getConnectionList() {
+ return connectionList;
+ }
+
+ public int getRange() {
+ return switch (droneLevel) {
+ case 1 -> 32;
+ case 2 -> 128;
+ case 3 -> 512;
+ default -> 0;
+ };
+ }
+
+ public Vec3Impl getCoords() {
+ return centreCoord;
+ }
+
+ private boolean tryConsumeDrone() {
+ List<ItemStack> inputs = getStoredInputs();
+ if (inputs.isEmpty()) return false;
+ for (ItemStack item : inputs) {
+ if (item != null && item.getItem() instanceof GT_TierDrone drone) {
+ this.droneLevel = drone.getLevel();
+ item.stackSize--;
+ updateSlots();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void tryUpdateDrone() {
+ List<ItemStack> inputs = getStoredInputs();
+ if (inputs.isEmpty()) return;
+ for (ItemStack item : inputs) {
+ if (item != null && item.getItem() instanceof GT_TierDrone drone) {
+ if (drone.getLevel() <= this.droneLevel) continue;
+ this.droneLevel = drone.getLevel();
+ item.stackSize--;
+ updateSlots();
+ return;
+ }
+ }
+ }
+
+ private void createRenderBlock() {
+ int x = getBaseMetaTileEntity().getXCoord();
+ int y = getBaseMetaTileEntity().getYCoord();
+ int z = getBaseMetaTileEntity().getZCoord();
+
+ double xOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetX;
+ double zOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetZ;
+ double yOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetY;
+
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), Blocks.air);
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), GregTech_API.sDroneRender);
+ }
+
+ private void destroyRenderBlock() {
+ int x = getBaseMetaTileEntity().getXCoord();
+ int y = getBaseMetaTileEntity().getYCoord();
+ int z = getBaseMetaTileEntity().getZCoord();
+
+ double xOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetX;
+ double zOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetZ;
+ double yOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetY;
+
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), Blocks.air);
+ }
+
+ private void fixAll() {
+ this.mWrench = this.mScrewdriver = this.mSoftHammer = this.mHardHammer = this.mCrowbar = this.mSolderingTool = true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ buildContext.addSyncedWindow(10, this::createMachineListWindow);
+ buildContext.addSyncedWindow(11, this::createCustomNameWindow);
+ builder.widget(// Machine List
+ new ButtonWidget().setOnClick(
+ (clickData, widget) -> {
+ if (!widget.isClient()) widget.getContext()
+ .openSyncedWindow(10);
+ })
+ .setSize(16, 16)
+ .setBackground(() -> {
+ List<UITexture> UI = new ArrayList<>();
+ UI.add(GT_UITextures.BUTTON_STANDARD);
+ UI.add(GT_UITextures.OVERLAY_BUTTON_WHITELIST);
+ return UI.toArray(new IDrawable[0]);
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_open_list"))
+ .setPos(94, 91)
+ .setEnabled(getBaseMetaTileEntity().isActive()))
+ .widget(// Turn on ALL machines
+ new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (!widget.isClient()) {
+ if (!getBaseMetaTileEntity().isActive()) {
+ GT_Utility.sendChatToPlayer(
+ widget.getContext()
+ .getPlayer(),
+ GT_Utility.trans("350", "You cannot control machine when drone centre shut down!"));
+ return;
+ }
+ for (DroneConnection mte : connectionList) {
+ mte.machine.getBaseMetaTileEntity()
+ .enableWorking();
+ }
+ GT_Utility.sendChatToPlayer(
+ widget.getContext()
+ .getPlayer(),
+ GT_Utility.trans("351", "Successfully turn on all machines!"));
+ widget.getContext()
+ .getPlayer()
+ .closeScreen();
+ }
+ })
+ .setSize(16, 16)
+ .setBackground(() -> {
+ List<UITexture> UI = new ArrayList<>();
+ UI.add(GT_UITextures.BUTTON_STANDARD);
+ UI.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON);
+ return UI.toArray(new IDrawable[0]);
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_poweron_all"))
+ .setPos(146, 91)
+ .setEnabled(getBaseMetaTileEntity().isActive()))
+ .widget(// Turn off ALL machines
+ new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (!widget.isClient()) {
+ if (!getBaseMetaTileEntity().isActive()) {
+ GT_Utility.sendChatToPlayer(
+ widget.getContext()
+ .getPlayer(),
+ GT_Utility.trans("350", "You cannot control machine when drone centre shut down!"));
+ return;
+ }
+ for (DroneConnection mte : connectionList) {
+ mte.machine.getBaseMetaTileEntity()
+ .disableWorking();
+ }
+ GT_Utility.sendChatToPlayer(
+ widget.getContext()
+ .getPlayer(),
+ GT_Utility.trans("352", "Successfully turn off all machines!"));
+ widget.getContext()
+ .getPlayer()
+ .closeScreen();
+ }
+ })
+ .setSize(16, 16)
+ .setBackground(() -> {
+ List<UITexture> UI = new ArrayList<>();
+ UI.add(GT_UITextures.BUTTON_STANDARD);
+ UI.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF);
+ return UI.toArray(new IDrawable[0]);
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_poweroff_all"))
+ .setPos(120, 91)
+ .setEnabled(getBaseMetaTileEntity().isActive()))
+ .widget(new FakeSyncWidget.ListSyncer<>(() -> connectionList, var1 -> {
+ connectionList.clear();
+ connectionList.addAll(var1);
+ }, (buffer, j) -> {
+ try {
+ buffer.writeNBTTagCompoundToBuffer(j.transConnectionToNBT());
+ } catch (IOException e) {
+ GT_Log.err.println(e.getCause());
+ }
+ }, buffer -> {
+ try {
+ return new DroneConnection(buffer.readNBTTagCompoundFromBuffer());
+ } catch (IOException e) {
+ GT_Log.err.println(e.getCause());
+ }
+ return null;
+ }));
+ }
+
+ protected ModularWindow createMachineListWindow(final EntityPlayer player) {
+ ModularWindow.Builder builder = ModularWindow.builder(260, 215);
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ builder.setGuiTint(getGUIColorization());
+ builder.widget(
+ ButtonWidget.closeWindowButton(true)
+ .setPos(245, 3));
+ builder.widget(
+ new TextWidget(EnumChatFormatting.BOLD + StatCollector.translateToLocal("GT5U.gui.text.drone_title"))
+ .setScale(2)
+ .setTextAlignment(Alignment.Center)
+ .setPos(0, 10)
+ .setSize(260, 8));
+ Scrollable MachineContainer = new Scrollable().setVerticalScroll();
+ for (int i = 0; i < connectionList.size(); i++) {
+ DroneConnection connection = connectionList.get(i);
+ ItemStackHandler drawitem = new ItemStackHandler(1);
+ drawitem.setStackInSlot(0, connection.machineItem);
+ DynamicPositionedRow row = new DynamicPositionedRow().setSynced(false);
+ GT_MetaTileEntity_MultiBlockBase coreMachine = connection.machine;
+ int finalI = i;
+ row.widget(
+ SlotWidget.phantom(drawitem, 0)
+ .disableInteraction()
+ .setPos(0, 0))
+ .widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ buttonID = finalI;
+ if (!widget.isClient()) widget.getContext()
+ .openSyncedWindow(11);
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_setname"))
+ .setBackground(
+ () -> new IDrawable[] { GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_PRINT })
+ .setSize(16, 16));
+ // Client can't handle unloaded machines
+ row.widget(
+ new ButtonWidget().setOnClick(
+ (clickData, widget) -> Optional.ofNullable(coreMachine)
+ .ifPresent(machine -> {
+ if (!getBaseMetaTileEntity().isActive()) {
+ GT_Utility.sendChatToPlayer(
+ player,
+ GT_Utility.trans("350", "You cannot control machine when drone centre shut down!"));
+ return;
+ }
+ if (machine.isAllowedToWork()) {
+ machine.disableWorking();
+ } else {
+ machine.enableWorking();
+ }
+ }))
+ .setPlayClickSoundResource(
+ () -> Optional.ofNullable(coreMachine)
+ .filter(GT_MetaTileEntity_MultiBlockBase::isAllowedToWork)
+ .map(var -> SoundResource.GUI_BUTTON_UP.resourceLocation)
+ .orElse(SoundResource.GUI_BUTTON_DOWN.resourceLocation))
+ .setBackground(
+ () -> Optional.ofNullable(coreMachine)
+ .map(
+ machine -> machine.isAllowedToWork()
+ ? new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON }
+ : new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF })
+ .orElse(new IDrawable[] { GT_UITextures.PICTURE_STALLED_ELECTRICITY }))
+ .attachSyncer(
+ new FakeSyncWidget.BooleanSyncer(
+ () -> Optional.ofNullable(coreMachine)
+ .map(GT_MetaTileEntity_MultiBlockBase::isAllowedToWork)
+ .orElse(false),
+ var -> Optional.ofNullable(coreMachine)
+ .ifPresent(machine -> {
+ if (var) machine.enableWorking();
+ else machine.disableWorking();
+ })),
+ builder)
+ .addTooltip(
+ coreMachine != null ? StatCollector.translateToLocal("GT5U.gui.button.power_switch")
+ : StatCollector.translateToLocal("GT5U.gui.button.drone_outofrange"))
+ .setSize(16, 16))
+ .widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (widget.isClient()) {
+ Optional.ofNullable(coreMachine)
+ .ifPresent(machine -> {
+ highlightMachine(player, machine);
+ player.closeScreen();
+ });
+ }
+ })
+ .addTooltip(
+ coreMachine != null ? StatCollector.translateToLocal("GT5U.gui.button.drone_highlight")
+ : StatCollector.translateToLocal("GT5U.gui.button.drone_outofrange"))
+ .setBackground(
+ () -> Optional.ofNullable(coreMachine)
+ .map(
+ machine -> new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_INVERT_REDSTONE })
+ .orElse(new IDrawable[] { GT_UITextures.OVERLAY_BUTTON_REDSTONE_OFF }))
+ .setSize(16, 16));
+ row.widget(
+ new TextWidget(
+ connectionList.get(i)
+ .getCustomName()).setTextAlignment(Alignment.CenterLeft)
+ .setPos(0, 4));
+ MachineContainer.widget(
+ row.setAlignment(MainAxisAlignment.SPACE_BETWEEN)
+ .setSpace(4)
+ .setPos(0, i * 20));
+ }
+ return builder.widget(
+ MachineContainer.setPos(10, 30)
+ .setSize(240, 160))
+ .setDraggable(false)
+ .build();
+ }
+
+ protected ModularWindow createCustomNameWindow(final EntityPlayer player) {
+ ModularWindow.Builder builder = ModularWindow.builder(150, 40);
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ builder.setGuiTint(getGUIColorization());
+ return builder.widget(
+ ButtonWidget.closeWindowButton(true)
+ .setPos(135, 3))
+ .widget(
+ new TextWidget("Custom Machine Name").setTextAlignment(Alignment.Center)
+ .setPos(0, 5)
+ .setSize(150, 8))
+ .widget(
+ new TextFieldWidget().setGetter(
+ () -> connectionList.get(buttonID)
+ .getCustomName())
+ .setSetter(
+ var -> connectionList.get(buttonID)
+ .setCustomName(var))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setTextColor(Color.WHITE.dark(1))
+ .setFocusOnGuiOpen(true)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD_LIGHT_GRAY.withOffset(-1, -1, 2, 2))
+ .setPos(10, 16)
+ .setSize(130, 16))
+ .build();
+ }
+
+ // Just like HIGHLIGHT_INTERFACE (and exactly from it)
+ private void highlightMachine(EntityPlayer player, GT_MetaTileEntity_MultiBlockBase machine) {
+ DimensionalCoord blockPos = new DimensionalCoord(
+ machine.getBaseMetaTileEntity()
+ .getXCoord(),
+ machine.getBaseMetaTileEntity()
+ .getYCoord(),
+ machine.getBaseMetaTileEntity()
+ .getZCoord(),
+ machine.getBaseMetaTileEntity()
+ .getWorld().provider.dimensionId);
+ WorldCoord blockPos2 = new WorldCoord((int) player.posX, (int) player.posY, (int) player.posZ);
+ BlockPosHighlighter.highlightBlock(
+ blockPos,
+ System.currentTimeMillis() + 500 * WorldCoord.getTaxicabDistance(blockPos, blockPos2));
+ }
+
+ public static HashMultimap<Integer, GT_MetaTileEntity_DroneCentre> getCentreMap() {
+ return droneMap;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_Hatch_DroneDownLink.java b/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_Hatch_DroneDownLink.java
new file mode 100644
index 0000000000..6e65033980
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_Hatch_DroneDownLink.java
@@ -0,0 +1,269 @@
+package gregtech.common.tileentities.machines.multi.drone;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizon.structurelib.util.Vec3Impl;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Maintenance;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.render.TextureFactory;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_Hatch_DroneDownLink extends GT_MetaTileEntity_Hatch_Maintenance {
+
+ private Vec3Impl downlinkCoord;
+ private DroneConnection connection;
+ // This has to be existed for doing random damage.
+ private GT_MetaTileEntity_MultiBlockBase machine;
+ private static final IIconContainer moduleActive = new Textures.BlockIcons.CustomIcon(
+ "iconsets/OVERLAY_DRONE_MODULE_ACTIVE");
+
+ public GT_MetaTileEntity_Hatch_DroneDownLink(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_Hatch_DroneDownLink(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures, false);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { "Built-in powerful navigation beacon!" };
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(IIconRegister aBlockIconRegister) {
+ super.registerIcons(aBlockIconRegister);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(moduleActive) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(moduleActive) };
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_DroneDownLink(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ downlinkCoord = new Vec3Impl(
+ getBaseMetaTileEntity().getXCoord(),
+ getBaseMetaTileEntity().getYCoord(),
+ getBaseMetaTileEntity().getZCoord());
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (hasConnection()) {
+ if (connection.centre.getBaseMetaTileEntity()
+ .isActive()) {
+ doNormalMaintain();
+ } else {
+ // Centre offline? ...do nothing.
+ // doRandomIssue();
+ }
+ } else {
+ // If the connection invalid, set it to null.
+ // Find connection every 10 second
+ if (aTick % 200 == 0) {
+ connection = null;
+ tryFindConnection();
+ // Let's have some "surprise". Sorry, surprise party is over.
+ // if (this.machine != null && this.machine.isValid()) {
+ // doRandomIssue();
+ }
+ }
+ }
+ }
+
+ private void doNormalMaintain() {
+ this.mWrench = this.mScrewdriver = this.mSoftHammer = this.mHardHammer = this.mCrowbar = this.mSolderingTool = true;
+ connection.machine.mWrench = connection.machine.mScrewdriver = connection.machine.mSoftHammer = connection.machine.mHardHammer = connection.machine.mCrowbar = connection.machine.mSolderingTool = true;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer, ForgeDirection side,
+ float aX, float aY, float aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void onRemoval() {
+ if (hasConnection()) connection.machine = null;
+ }
+
+ private boolean hasConnection() {
+ if (connection == null) return false;
+ if (connection.isValid()) return true;
+ return connection.reCheckConnection();
+ }
+
+ /**
+ * Find a drone connection. This will search for all DC in the same dimension, then find one in range.
+ */
+ private void tryFindConnection() {
+ if (GT_MetaTileEntity_DroneCentre.getCentreMap()
+ .containsKey(getBaseMetaTileEntity().getWorld().provider.dimensionId)) {
+ List<GT_MetaTileEntity_DroneCentre> target = GT_MetaTileEntity_DroneCentre.getCentreMap()
+ .get(getBaseMetaTileEntity().getWorld().provider.dimensionId)
+ .stream()
+ .collect(Collectors.toList());
+ for (GT_MetaTileEntity_DroneCentre centre : target) {
+ if (centre.getCoords()
+ .withinDistance(this.downlinkCoord, centre.getRange())
+ && centre.getBaseMetaTileEntity()
+ .isActive()) {
+ GT_MetaTileEntity_MultiBlockBase machine = tryFindCoreGTMultiBlock();
+ if (machine != null && machine.isValid()) {
+ this.machine = machine;
+ connection = new DroneConnection(machine, centre);
+ connection.centre.getConnectionList()
+ .add(connection);
+ }
+ }
+ }
+ }
+ }
+
+ private void doRandomIssue() {
+ switch (getBaseMetaTileEntity().getRandomNumber(6)) {
+ case 0 -> machine.mWrench = !machine.mWrench;
+ case 1 -> machine.mScrewdriver = !machine.mScrewdriver;
+ case 2 -> machine.mSoftHammer = !machine.mSoftHammer;
+ case 3 -> machine.mCrowbar = !machine.mCrowbar;
+ case 4 -> machine.mSolderingTool = !connection.machine.mSolderingTool;
+ case 5 -> machine.mHardHammer = !connection.machine.mHardHammer;
+ }
+ }
+
+ // Find mainframe. Mainly from a method in GT_API——This will cause performance issue! Do not call it frequently.
+ private GT_MetaTileEntity_MultiBlockBase tryFindCoreGTMultiBlock() {
+ Queue<ChunkCoordinates> tQueue = new LinkedList<>();
+ Set<ChunkCoordinates> visited = new HashSet<>(80);
+ tQueue.add(
+ this.getBaseMetaTileEntity()
+ .getCoords());
+ World world = this.getBaseMetaTileEntity()
+ .getWorld();
+ while (!tQueue.isEmpty()) {
+ final ChunkCoordinates aCoords = tQueue.poll();
+ final TileEntity tTileEntity;
+ final boolean isMachineBlock;
+ tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ);
+ isMachineBlock = GregTech_API.isMachineBlock(
+ world.getBlock(aCoords.posX, aCoords.posY, aCoords.posZ),
+ world.getBlockMetadata(aCoords.posX, aCoords.posY, aCoords.posZ));
+
+ // See if the block itself is MultiBlock, also the one we need.
+ if (tTileEntity instanceof IGregTechTileEntity te
+ && te.getMetaTileEntity() instanceof GT_MetaTileEntity_MultiBlockBase mte)
+ if (mte.mMaintenanceHatches.contains(this)) return mte;
+
+ // Now see if we should add the nearby blocks to the queue:
+ // 1) If we've visited less than 5 blocks, then yes
+ // 2) If the tile says we should recursively update (pipes don't, machine blocks do)
+ // 3) If the block at the coordinates is marked as a machine block
+ if (visited.size() < 5
+ || (tTileEntity instanceof IMachineBlockUpdateable
+ && ((IMachineBlockUpdateable) tTileEntity).isMachineBlockUpdateRecursive())
+ || isMachineBlock) {
+ ChunkCoordinates tCoords;
+
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX + 1, aCoords.posY, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX - 1, aCoords.posY, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY + 1, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY - 1, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ + 1)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ - 1)))
+ tQueue.add(tCoords);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y,
+ int z) {
+ super.getWailaNBTData(player, tile, tag, world, x, y, z);
+ tag.setBoolean("connection", connection == null);
+ if (connection != null) {
+ tag.setInteger("x", connection.centreCoord.posX);
+ tag.setInteger("y", connection.centreCoord.posY);
+ tag.setInteger("z", connection.centreCoord.posZ);
+ }
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ NBTTagCompound tag = accessor.getNBTData();
+ currenttip.add(
+ tag.getBoolean("connection")
+ ? EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.waila.drone_downlink.noConnection")
+ : EnumChatFormatting.AQUA + StatCollector.translateToLocal("GT5U.waila.drone_downlink.connection")
+ + tag.getInteger("x")
+ + " "
+ + tag.getInteger("y")
+ + " "
+ + tag.getInteger("z"));
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ }
+}