package gregtech.common.tileentities.debug; import static gregtech.GTMod.GT_FML_LOGGER; import static net.minecraft.util.StatCollector.translateToLocal; import java.util.HashMap; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ChatComponentTranslation; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.ForgeDirection; import org.lwjgl.opengl.GL11; import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing; import com.gtnewhorizon.structurelib.structure.StructureUtility; import com.gtnewhorizon.structurelib.util.Vec3Impl; import com.gtnewhorizons.modularui.api.drawable.IDrawable; 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.CycleButtonWidget; import com.gtnewhorizons.modularui.common.widget.DrawableWidget; import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; import com.gtnewhorizons.modularui.common.widget.TextWidget; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.enums.Textures; import gregtech.api.gui.modularui.GTUIInfos; import gregtech.api.gui.modularui.GTUITextures; import gregtech.api.gui.modularui.GUITextureSet; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.modularui.IAddGregtechLogo; import gregtech.api.interfaces.modularui.IAddUIWidgets; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.implementations.MTETieredMachineBlock; import gregtech.api.render.TextureFactory; public class MTEAdvDebugStructureWriter extends MTETieredMachineBlock implements IAddGregtechLogo, IAddUIWidgets { private static final HashMap bondingBoxes = new HashMap<>(1); private final BoundHighlighter boundingBox = new BoundHighlighter(); private final short[] numbers = new short[6]; private boolean transpose = false; private boolean showHighlightBox = true; private String[] result = new String[] { "Undefined" }; public MTEAdvDebugStructureWriter(int aID, String aName, String aNameRegional, int aTier) { super(aID, aName, aNameRegional, aTier, 0, ""); } public MTEAdvDebugStructureWriter(String aName, int aTier, String aDescription, ITexture[][][] aTextures) { super(aName, aTier, 0, aDescription, aTextures); } @Override public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { return new MTEAdvDebugStructureWriter(mName, mTier, "", mTextures); } @Override public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection, ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) { return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][colorIndex + 1], sideDirection != facingDirection ? TextureFactory.of( TextureFactory.builder() .addIcon(Textures.BlockIcons.OVERLAY_TELEPORTER_ACTIVE) .glow() .build()) : TextureFactory.of( TextureFactory.builder() .addIcon(Textures.BlockIcons.STRUCTURE_MARK) .glow() .build()) }; } @Override public ITexture[][][] getTextureSet(ITexture[] aTextures) { return null; } @Override public boolean allowPutStack(IGregTechTileEntity iGregTechTileEntity, int i, ForgeDirection b, ItemStack itemStack) { return false; } @Override public boolean allowPullStack(IGregTechTileEntity iGregTechTileEntity, int i, ForgeDirection b, ItemStack itemStack) { return false; } @Override public void saveNBTData(NBTTagCompound aNBT) { for (int i = 0; i < numbers.length; i++) { aNBT.setShort("eData" + i, numbers[i]); } aNBT.setBoolean("Transpose", transpose); aNBT.setBoolean("HighlightBox", showHighlightBox); } @Override public void loadNBTData(NBTTagCompound aNBT) { for (int i = 0; i < numbers.length; i++) { numbers[i] = aNBT.getShort("eData" + i); } transpose = aNBT.getBoolean("Transpose"); showHighlightBox = aNBT.getBoolean("HighlightBox"); } @Override public boolean isSimpleMachine() { return false; } @Override public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) { super.onFirstTick(aBaseMetaTileEntity); bondingBoxes.put(this, boundingBox); } @Override public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { if (aBaseMetaTileEntity.isServerSide()) { ExtendedFacing writerFacing = ExtendedFacing.of(aBaseMetaTileEntity.getFrontFacing()); double[] abc = new double[3]; double[] xyz = new double[3]; boundingBox.dim = aBaseMetaTileEntity.getWorld().provider.dimensionId; boundingBox.showHighlightBox = showHighlightBox; abc[0] = -numbers[0] - 0.5; abc[1] = -numbers[1] - 0.5; abc[2] = -numbers[2] - 0.5; writerFacing.getWorldOffset(abc, xyz); boundingBox.pos1 = new Vec3Impl( aBaseMetaTileEntity.getXCoord() + (int) (xyz[0] + 0.5), aBaseMetaTileEntity.getYCoord() + (int) (xyz[1] + 0.5), aBaseMetaTileEntity.getZCoord() + (int) (xyz[2] + 0.5)); abc[0] = -numbers[0] + numbers[3] - 0.5; abc[1] = -numbers[1] + numbers[4] - 0.5; abc[2] = -numbers[2] + numbers[5] - 0.5; writerFacing.getWorldOffset(abc, xyz); boundingBox.pos2 = new Vec3Impl( aBaseMetaTileEntity.getXCoord() + (int) (xyz[0] + 0.5), aBaseMetaTileEntity.getYCoord() + (int) (xyz[1] + 0.5), aBaseMetaTileEntity.getZCoord() + (int) (xyz[2] + 0.5)); } } @Override public void onRemoval() { bondingBoxes.remove(this); } @Override public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) { IGregTechTileEntity aBaseMetaTileEntity = getBaseMetaTileEntity(); printStructure(aPlayer); aBaseMetaTileEntity.disableWorking(); } public void printStructure(EntityPlayer aPlayer) { IGregTechTileEntity aBaseMetaTileEntity = getBaseMetaTileEntity(); String pseudoJavaCode = StructureUtility.getPseudoJavaCode( aBaseMetaTileEntity.getWorld(), ExtendedFacing.of(aBaseMetaTileEntity.getFrontFacing()), aBaseMetaTileEntity.getXCoord(), aBaseMetaTileEntity.getYCoord(), aBaseMetaTileEntity.getZCoord(), numbers[0], numbers[1], numbers[2], te -> te.getClass() .getCanonicalName(), numbers[3], numbers[4], numbers[5], transpose); GT_FML_LOGGER.info(pseudoJavaCode); result = pseudoJavaCode.split("\\n"); aPlayer.addChatMessage( new ChatComponentTranslation(translateToLocal("GT5U.machines.advdebugstructurewriter.printed"))); } @Override public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) { GTUIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer); return true; } @Override public boolean isFacingValid(ForgeDirection facing) { return true; } @Override public boolean isElectric() { return false; } @Override public boolean isAccessAllowed(EntityPlayer aPlayer) { return true; } @Override public String[] getDescription() { return new String[] { translateToLocal("GT5U.machines.advdebugstructurewriter.tooltip"), // Scans Blocks Around translateToLocal("GT5U.machines.advdebugstructurewriter.tooltip.1"), // Prints Multiblock NonTE // structure check code translateToLocal("GT5U.machines.advdebugstructurewriter.tooltip.2") // ABC axes aligned to machine front }; } @Override public boolean isGivingInformation() { return true; } @Override public String[] getInfoData() { return result; } @Override public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { builder.widget( new DrawableWidget().setDrawable(GTUITextures.PICTURE_SCREEN_BLACK) .setSize(90, 112) .setPos(43, 4)) .widget(new ButtonWidget().setOnClick((clickData, widget) -> { if (getBaseMetaTileEntity().isServerSide()) { printStructure( widget.getContext() .getPlayer()); } }) .setBackground(GTUITextures.BUTTON_STANDARD, GTUITextures.OVERLAY_BUTTON_PRINT) .setSize(18, 18) .setPos(11, 128) .addTooltip(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.print.tooltip"))) .widget( new CycleButtonWidget().setToggle(() -> transpose, aBoolean -> transpose = aBoolean) .setVariableBackground(GTUITextures.BUTTON_STANDARD_TOGGLE) .setStaticTexture(GTUITextures.OVERLAY_BUTTON_TRANSPOSE) .setSize(18, 18) .setPos(32, 128) .addTooltip(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.transpose.tooltip"))) .widget( new CycleButtonWidget().setToggle(() -> showHighlightBox, aBoolean -> showHighlightBox = aBoolean) .setVariableBackground(GTUITextures.BUTTON_STANDARD_TOGGLE) .setStaticTexture(GTUITextures.OVERLAY_BUTTON_BOUNDING_BOX) .setSize(18, 18) .setPos(53, 128) .addTooltip(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.highlight.tooltip"))) .widget( new MultiChildWidget() .addChild( new TextWidget(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.origin")) .setDefaultColor(0xf0f0ff) .setPos(0, 0)) .addChild( TextWidget.dynamicString(() -> "A: " + numbers[0]) .setDefaultColor(0xf0f0ff) .setPos(0, 10)) .addChild( TextWidget.dynamicString(() -> "B: " + numbers[1]) .setDefaultColor(0xf0f0ff) .setPos(0, 18)) .addChild( TextWidget.dynamicString(() -> "C: " + numbers[2]) .setDefaultColor(0xf0f0ff) .setPos(0, 26)) .addChild( new TextWidget(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.size")) .setDefaultColor(0xf0f0ff) .setPos(0, 52)) .addChild( TextWidget.dynamicString(() -> "A: " + numbers[3]) .setDefaultColor(0xf0f0ff) .setPos(0, 62)) .addChild( TextWidget.dynamicString(() -> "B: " + numbers[4]) .setDefaultColor(0xf0f0ff) .setPos(0, 70)) .addChild( TextWidget.dynamicString(() -> "C: " + numbers[5]) .setDefaultColor(0xf0f0ff) .setPos(0, 78)) .setPos(46, 8)); addChangeNumberButtons(builder, GTUITextures.OVERLAY_BUTTON_MINUS_LARGE, -512, -64, 7); addChangeNumberButtons(builder, GTUITextures.OVERLAY_BUTTON_MINUS_SMALL, -16, -1, 25); addChangeNumberButtons(builder, GTUITextures.OVERLAY_BUTTON_PLUS_SMALL, 16, 1, 133); addChangeNumberButtons(builder, GTUITextures.OVERLAY_BUTTON_PLUS_LARGE, 512, 64, 151); } private void addChangeNumberButtons(ModularWindow.Builder builder, IDrawable overlay, int addNumberShift, int addNumber, int xPos) { int[] yPos = new int[] { 4, 22, 40, 62, 80, 98 }; for (int i = 0; i < yPos.length; i++) { final int index = i; // needed for lambda builder.widget(new ButtonWidget().setOnClick((clickData, widget) -> { numbers[index] += clickData.shift ? addNumberShift : addNumber; if (index >= 3) { numbers[index] = (short) Math.max(numbers[index], 0); } }) .setBackground(GTUITextures.BUTTON_STANDARD, overlay) .setSize(18, 18) .setPos(xPos, yPos[index])); } } @Override public GUITextureSet getGUITextureSet() { return new GUITextureSet().setGregTechLogo(GTUITextures.PICTURE_GT_LOGO_17x17_TRANSPARENT_GRAY); } @Override public void addGregTechLogo(ModularWindow.Builder builder) { builder.widget( new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo()) .setSize(17, 17) .setPos(113, 96)); } @Override public boolean doesBindPlayerInventory() { return false; } public static class ForgeEventHandler { public ForgeEventHandler() { MinecraftForge.EVENT_BUS.register(this); } @SuppressWarnings("unused") @SideOnly(Side.CLIENT) @SubscribeEvent public void onRenderWorldLast(RenderWorldLastEvent e) { for (BoundHighlighter boundingBox : bondingBoxes.values()) { boundingBox.renderHighlightedBlock(e); } } } private static class BoundHighlighter { public Vec3Impl pos1; public Vec3Impl pos2; public boolean showHighlightBox; public int dim; @SideOnly(Side.CLIENT) private void renderHighlightedBlock(RenderWorldLastEvent event) { if (pos1 == null || pos2 == null || !showHighlightBox) { return; } Minecraft mc = Minecraft.getMinecraft(); int dimension = mc.theWorld.provider.dimensionId; if (dimension != dim) { pos1 = null; pos2 = null; return; } EntityPlayerSP p = mc.thePlayer; double doubleX = p.lastTickPosX + (p.posX - p.lastTickPosX) * event.partialTicks; double doubleY = p.lastTickPosY + (p.posY - p.lastTickPosY) * event.partialTicks; double doubleZ = p.lastTickPosZ + (p.posZ - p.lastTickPosZ) * event.partialTicks; GL11.glPushMatrix(); GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); GL11.glLineWidth(3); GL11.glTranslated(-doubleX, -doubleY, -doubleZ); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); renderHighLightedArenaOutline(pos1.get0(), pos1.get1(), pos1.get2(), pos2.get0(), pos2.get1(), pos2.get2()); GL11.glPopAttrib(); GL11.glPopMatrix(); } @SideOnly(Side.CLIENT) static void renderHighLightedArenaOutline(double x1, double y1, double z1, double x2, double y2, double z2) { GL11.glBegin(GL11.GL_LINE_STRIP); GL11.glVertex3d(x1, y1, z1); GL11.glVertex3d(x1, y2, z1); GL11.glVertex3d(x1, y2, z2); GL11.glVertex3d(x1, y1, z2); GL11.glVertex3d(x1, y1, z1); GL11.glVertex3d(x2, y1, z1); GL11.glVertex3d(x2, y2, z1); GL11.glVertex3d(x2, y2, z2); GL11.glVertex3d(x2, y1, z2); GL11.glVertex3d(x2, y1, z1); GL11.glVertex3d(x1, y1, z1); GL11.glVertex3d(x2, y1, z1); GL11.glVertex3d(x2, y1, z2); GL11.glVertex3d(x1, y1, z2); GL11.glVertex3d(x1, y2, z2); GL11.glVertex3d(x2, y2, z2); GL11.glVertex3d(x2, y2, z1); GL11.glVertex3d(x2, y1, z1); GL11.glVertex3d(x1, y1, z1); GL11.glVertex3d(x2, y1, z1); GL11.glVertex3d(x2, y2, z1); GL11.glVertex3d(x1, y2, z1); GL11.glVertex3d(x1, y2, z2); GL11.glVertex3d(x2, y2, z2); GL11.glVertex3d(x2, y1, z2); GL11.glVertex3d(x1, y1, z2); GL11.glEnd(); } } }