package pneumaticCraft.client.gui;
import igwmod.gui.GuiWiki;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;
import net.minecraft.world.ChunkPosition;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import pneumaticCraft.PneumaticCraft;
import pneumaticCraft.client.gui.widget.GuiCheckBox;
import pneumaticCraft.client.gui.widget.GuiRadioButton;
import pneumaticCraft.client.gui.widget.IGuiWidget;
import pneumaticCraft.client.gui.widget.WidgetTextField;
import pneumaticCraft.common.config.Config;
import pneumaticCraft.common.inventory.ContainerProgrammer;
import pneumaticCraft.common.network.NetworkHandler;
import pneumaticCraft.common.network.PacketGuiButton;
import pneumaticCraft.common.network.PacketProgrammerUpdate;
import pneumaticCraft.common.network.PacketUpdateTextfield;
import pneumaticCraft.common.progwidgets.IProgWidget;
import pneumaticCraft.common.progwidgets.ProgWidgetArea;
import pneumaticCraft.common.progwidgets.ProgWidgetCoordinate;
import pneumaticCraft.common.progwidgets.ProgWidgetCoordinateOperator;
import pneumaticCraft.common.progwidgets.ProgWidgetStart;
import pneumaticCraft.common.progwidgets.WidgetRegistrator;
import pneumaticCraft.common.tileentity.TileEntityProgrammer;
import pneumaticCraft.common.util.PneumaticCraftUtils;
import pneumaticCraft.lib.ModIds;
import pneumaticCraft.lib.Textures;
import codechicken.nei.VisiblityData;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.Optional;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class GuiProgrammer extends GuiPneumaticContainerBase<TileEntityProgrammer>{
private final EntityPlayer player;
private GuiPastebin pastebinGui;
// private GuiButton redstoneButton;
private GuiButtonSpecial importButton;
private GuiButtonSpecial exportButton;
private GuiButtonSpecial allWidgetsButton;
private List<GuiRadioButton> difficultyButtons;
private GuiCheckBox showInfo, showFlow;
private WidgetTextField nameField;
private GuiButtonSpecial undoButton, redoButton;
private GuiButtonSpecial convertToRelativeButton;
private final List<IProgWidget> visibleSpawnWidgets = new ArrayList<IProgWidget>();
private GuiUnitProgrammer programmerUnit;
private boolean wasClicking;
private boolean wasFocused;
private IProgWidget draggingWidget;
private int lastMouseX, lastMouseY;
private int dragMouseStartX, dragMouseStartY;
private int dragWidgetStartX, dragWidgetStartY;
private static final int FAULT_MARGIN = 4;
private int widgetPage;
private int maxPage;
private boolean showingAllWidgets;
private int showingWidgetProgress;
private int oldShowingWidgetProgress;
private static final int PROGRAMMING_START_Y = 17;
private static final int PROGRAMMING_START_X = 5;
private static final int PROGRAMMING_WIDTH = 294;
private static final int PROGRAMMING_HEIGHT = 154;
public GuiProgrammer(InventoryPlayer player, TileEntityProgrammer te){
super(new ContainerProgrammer(player, te), te, Textures.GUI_PROGRAMMER);
ySize = 256;
xSize = 350;
this.player = FMLClientHandler.instance().getClient().thePlayer;
}
private void updateVisibleProgWidgets(){
int y = 0, page = 0;
int xSpacing = 22;
int x = 322 - maxPage * xSpacing;
boolean showAllWidgets = showingWidgetProgress == xSpacing * maxPage && showingAllWidgets;
maxPage = 0;
visibleSpawnWidgets.clear();
int difficulty = 0;
for(int i = 0; i < difficultyButtons.size(); i++) {
if(difficultyButtons.get(i).checked) {
difficulty = i;
break;
}
}
for(IProgWidget widget : WidgetRegistrator.registeredWidgets) {
if(difficulty >= widget.getDifficulty().ordinal()) {
widget.setY(y + 40);
widget.setX(showAllWidgets ? x : 322);
int widgetHeight = widget.getHeight() / 2 + (widget.hasStepOutput() ? 5 : 0) + 1;
y += widgetHeight;
if(showAllWidgets || page == widgetPage) visibleSpawnWidgets.add(widget);
if(y > ySize - 160) {
y = 0;
x += xSpacing;
page++;
maxPage++;
}
}
}
if(widgetPage > maxPage) {
widgetPage = maxPage;
updateVisibleProgWidgets();
}
}
@Override
protected boolean shouldAddInfoTab(){
return false;
}
@Override
public void initGui(){
if(pastebinGui != null && pastebinGui.outputTag != null) {
te.readProgWidgetsFromNBT(pastebinGui.outputTag);
pastebinGui = null;
NetworkHandler.sendToServer(new PacketProgrammerUpdate(te));
}
super.initGui();
if(programmerUnit != null) {
te.translatedX = programmerUnit.getTranslatedX();
te.translatedY = programmerUnit.getTranslatedY();
te.zoomState = programmerUnit.getLastZoom();
}
programmerUnit = new GuiUnitProgrammer(te.progWidgets, fontRendererObj, guiLeft, guiTop, xSize, width, height, PROGRAMMING_START_X, PROGRAMMING_START_Y, PROGRAMMING_WIDTH, PROGRAMMING_HEIGHT, te.translatedX, te.translatedY, te.zoomState);
addWidget(programmerUnit.getScrollBar());
int xStart = (width - xSize) / 2;
int yStart = (height - ySize) / 2;
// addProgWidgetTabs(xStart, yStart);
importButton = new GuiButtonSpecial(1, xStart + 301, yStart + 3, 20, 15, "<--");
importButton.setTooltipText("Import program");
buttonList.add(importButton);
exportButton = new GuiButtonSpecial(2, xStart + 301, yStart + 20, 20, 15, "-->");
buttonList.add(exportButton);
buttonList.add(new GuiButton(3, xStart + 294, yStart + 174, 10, 10, "-"));
buttonList.add(new GuiButton(4, xStart + 335, yStart + 174, 10, 10, "+"));
allWidgetsButton = new GuiButtonSpecial(8, xStart + 321, yStart + 159, 10, 10, "<");
allWidgetsButton.setTooltipText(I18n.format("gui.programmer.button.openPanel.tooltip"));
addWidget(allWidgetsButton);
difficultyButtons = new ArrayList<GuiRadioButton>();
for(int i = 0; i < IProgWidget.WidgetDifficulty.values().length; i++) {
GuiRadioButton radioButton = new GuiRadioButton(i, xStart + 263, yStart + 200 + i * 12, 0xFF000000, IProgWidget.WidgetDifficulty.values()[i].getLocalizedName());
radioButton.checked = Config.getProgrammerDifficulty() == i;
addWidget(radioButton);
difficultyButtons.add(radioButton);
radioButton.otherChoices = difficultyButtons;
if(i == 1) radioButton.setTooltip(I18n.format("gui.programmer.difficulty.medium.tooltip"));
if(i == 2) radioButton.setTooltip(I18n.format("gui.programmer.difficulty.advanced.tooltip"));
}
buttonList.add(new GuiButton(5, xStart + 5, yStart + 175, 87, 20, I18n.format("gui.programmer.button.showStart")));
buttonList.add(new GuiButton(6, xStart + 5, yStart + 197, 87, 20, I18n.format("gui.programmer.button.showLatest")));
addWidget(showInfo = new GuiCheckBox(-1, xStart + 5, yStart + 220, 0xFF000000, "gui.programmer.checkbox.showInfo").setChecked(te.showInfo));
addWidget(showFlow = new GuiCheckBox(-1, xStart + 5, yStart + 232, 0xFF000000, "gui.programmer.checkbox.showFlow").setChecked(te.showFlow));
GuiButtonSpecial pastebinButton = new GuiButtonSpecial(7, guiLeft - 24, guiTop + 44, 20, 20, "");
pastebinButton.setTooltipText(I18n.format("gui.remote.button.pastebinButton"));
pastebinButton.setRenderedIcon(Textures.GUI_PASTEBIN_ICON_LOCATION);
buttonList.add(pastebinButton);
undoButton = new GuiButtonSpecial(9, guiLeft - 24, guiTop + 2, 20, 20, "");
redoButton = new GuiButtonSpecial(10, guiLeft - 24, guiTop + 23, 20, 20, "");
GuiButtonSpecial clearAllButton = new GuiButtonSpecial(11, guiLeft - 24, guiTop + 65, 20, 20, "");
convertToRelativeButton = new GuiButtonSpecial(12, guiLeft - 24, guiTop + 86, 20, 20, "Rel");
undoButton.setRenderedIcon(Textures.GUI_UNDO_ICON_LOCATION);
redoButton.setRenderedIcon(Textures.GUI_REDO_ICON_LOCATION);
clearAllButton.setRenderedIcon(Textures.GUI_DELETE_ICON_LOCATION);
undoButton.setTooltipText(I18n.format("gui.programmer.button.undoButton.tooltip"));
redoButton.setTooltipText(I18n.format("gui.programmer.button.redoButton.tooltip"));
clearAllButton.setTooltipText(I18n.format("gui.programmer.button.clearAllButton.tooltip"));
buttonList.add(undoButton);
buttonList.add(redoButton);
buttonList.add(clearAllButton);
buttonList.add(convertToRelativeButton);
String containerName = te.hasCustomInventoryName() ? te.getInventoryName() : StatCollector.translateToLocal(te.getInventoryName() + ".name");
addLabel(containerName, guiLeft + 7, guiTop + 5);
nameField = new WidgetTextField(fontRendererObj, guiLeft + 200, guiTop + 5, 98, fontRendererObj.FONT_HEIGHT);
addWidget(nameField);
String name = I18n.format("gui.programmer.name");
addLabel(name, guiLeft + 197 - fontRendererObj.getStringWidth(name), guiTop + 5);
updateVisibleProgWidgets();
}
@Override
protected Point getInvNameOffset(){
return null;
}
@Override
protected Point getInvTextOffset(){
return null;
}
@Override
protected boolean shouldAddProblemTab(){
return false;
}
@Override
protected void drawGuiContainerForegroundLayer(int x, int y){
super.drawGuiContainerForegroundLayer(x, y);
boolean igwLoaded = Loader.isModLoaded(ModIds.IGWMOD);
fontRendererObj.drawString(widgetPage + 1 + "/" + (maxPage + 1), 305, 175, 0xFF000000);
fontRendererObj.drawString(I18n.format("gui.programmer.difficulty"), 263, 190, 0xFF000000);
if(showingWidgetProgress == 0) {
programmerUnit.renderForeground(x, y, draggingWidget);
}
for(IProgWidget widget : visibleSpawnWidgets) {
if(widget != draggingWidget && x - guiLeft >= widget.getX() && y - guiTop >= widget.getY() && x - guiLeft <= widget.getX() + widget.getWidth() / 2 && y - guiTop <= widget.getY() + widget.getHeight() / 2) {
List<String> tooltip = new ArrayList<String>();
widget.getTooltip(tooltip);
if(igwLoaded) tooltip.add(I18n.format("gui.programmer.pressIForInfo"));
if(tooltip.size() > 0) drawHoveringString(tooltip, x - guiLeft, y - guiTop, fontRendererObj);
}
}
}
@Override
protected void keyTyped(char key, int keyCode){
super.keyTyped(key, keyCode);
if(Keyboard.KEY_I == keyCode && Loader.isModLoaded(ModIds.IGWMOD)) {
onIGWAction();
}
if(Keyboard.KEY_R == keyCode) {
if(exportButton.getBounds().contains(lastMouseX, lastMouseY)) {
NetworkHandler.sendToServer(new PacketGuiButton(0));
}
}
if(Keyboard.KEY_SPACE == keyCode) {
toggleShowWidgets();
}
if(Keyboard.KEY_DELETE == keyCode) {
IProgWidget widget = programmerUnit.getHoveredWidget(lastMouseX, lastMouseY);
if(widget != null) {
te.progWidgets.remove(widget);
NetworkHandler.sendToServer(new PacketProgrammerUpdate(te));
}
}
if(Keyboard.KEY_Z == keyCode) {
NetworkHandler.sendToServer(new PacketGuiButton(undoButton.id));
}
if(Keyboard.KEY_Y == keyCode) {
NetworkHandler.sendToServer(new PacketGuiButton(redoButton.id));
}
}
@Optional.Method(modid = ModIds.IGWMOD)
private void onIGWAction(){
int x = lastMouseX;
int y = lastMouseY;
IProgWidget hoveredWidget = programmerUnit.getHoveredWidget(x, y);
if(hoveredWidget != null) {
GuiWiki gui = new GuiWiki();
FMLClientHandler.instance().showGuiScreen(gui);
gui.setCurrentFile("pneumaticcraft:progwidget/" + hoveredWidget.getWidgetString());
}
for(IProgWidget widget : visibleSpawnWidgets) {
if(widget != draggingWidget && x - guiLeft >= widget.getX() && y - guiTop >= widget.getY() && x - guiLeft <= widget.getX() + widget.getWidth() / 2 && y - guiTop <= widget.getY() + widget.getHeight() / 2) {
GuiWiki gui = new GuiWiki();
FMLClientHandler.instance().showGuiScreen(gui);
gui.setCurrentFile("pneumaticcraft:progwidget/" + widget.getWidgetString());
}
}
}
@Override
protected boolean shouldDrawBackground(){
return false;
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int x, int y){
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
bindGuiTexture();
int xStart = (width - xSize) / 2;
int yStart = (height - ySize) / 2;
func_146110_a(xStart, yStart, 0, 0, xSize, ySize, xSize, ySize);
programmerUnit.getScrollBar().setEnabled(showingWidgetProgress == 0);
super.drawGuiContainerBackgroundLayer(partialTicks, x, y);
if(showingWidgetProgress > 0) programmerUnit.getScrollBar().setCurrentState(programmerUnit.getLastZoom());
programmerUnit.render(x, y, showFlow.checked, showInfo.checked && showingWidgetProgress == 0, draggingWidget == null);
int origX = x;
int origY = y;
x -= programmerUnit.getTranslatedX();
y -= programmerUnit.getTranslatedY();
float scale = programmerUnit.getScale();
x = (int)(x / scale);
y = (int)(y / scale);
if(showingWidgetProgress > 0) {
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
bindGuiTexture();
int width = oldShowingWidgetProgress + (int)((showingWidgetProgress - oldShowingWidgetProgress) * partialTicks);
for(int i = 0; i < width; i++) {
func_146110_a(xStart + 320 - i, yStart + 36, 323, 36, 1, 136, xSize, ySize);
}
func_146110_a(xStart + 319 - width, yStart + 36, 319, 36, 2, 136, xSize, ySize);
if(showingAllWidgets && draggingWidget != null) toggleShowWidgets();
}
GL11.glEnable(GL11.GL_TEXTURE_2D);
for(IProgWidget widget : visibleSpawnWidgets) {
GL11.glPushMatrix();
GL11.glTranslated(widget.getX() + guiLeft, widget.getY() + guiTop, 0);
GL11.glScaled(0.5, 0.5, 1);
widget.render();
GL11.glPopMatrix();
}
GL11.glPushMatrix();
GL11.glTranslated(programmerUnit.getTranslatedX(), programmerUnit.getTranslatedY(), 0);
GL11.glScaled(scale, scale, 1);
if(draggingWidget != null) {
GL11.glPushMatrix();
GL11.glTranslated(draggingWidget.getX() + guiLeft, draggingWidget.getY() + guiTop, 0);
GL11.glScaled(0.5, 0.5, 1);
draggingWidget.render();
GL11.glPopMatrix();
}
GL11.glPopMatrix();
boolean isLeftClicking = Mouse.isButtonDown(0);
boolean isMiddleClicking = GameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindPickBlock);
if(draggingWidget != null) {
setConnectingWidgetsToXY(draggingWidget, x - dragMouseStartX + dragWidgetStartX - guiLeft, y - dragMouseStartY + dragWidgetStartY - guiTop);
}
if(isLeftClicking && !wasClicking) {
for(IProgWidget widget : visibleSpawnWidgets) {
if(origX >= widget.getX() + guiLeft && origY >= widget.getY() + guiTop && origX <= widget.getX() + guiLeft + widget.getWidth() / 2 && origY <= widget.getY() + guiTop + widget.getHeight() / 2) {
draggingWidget = widget.copy();
te.progWidgets.add(draggingWidget);
dragMouseStartX = x - (int)(guiLeft / scale);
dragMouseStartY = y - (int)(guiTop / scale);
dragWidgetStartX = (int)((widget.getX() - programmerUnit.getTranslatedX()) / scale);
dragWidgetStartY = (int)((widget.getY() - programmerUnit.getTranslatedY()) / scale);
break;
}
}
if(draggingWidget == null && showingWidgetProgress == 0) {
IProgWidget widget = programmerUnit.getHoveredWidget(origX, origY);
if(widget != null) {
draggingWidget = widget;
dragMouseStartX = x - guiLeft;
dragMouseStartY = y - guiTop;
dragWidgetStartX = widget.getX();
dragWidgetStartY = widget.getY();
}
}
} else if(isMiddleClicking && !wasClicking && showingWidgetProgress == 0) {
IProgWidget widget = programmerUnit.getHoveredWidget(origX, origY);
if(widget != null) {
draggingWidget = widget.copy();
te.progWidgets.add(draggingWidget);
dragMouseStartX = 0;
dragMouseStartY = 0;
dragWidgetStartX = widget.getX() - (x - guiLeft);
dragWidgetStartY = widget.getY() - (y - guiTop);
if(PneumaticCraft.proxy.isSneakingInGui()) copyAndConnectConnectingWidgets(widget, draggingWidget);
}
}
if(!isLeftClicking && !isMiddleClicking && draggingWidget != null) {
if(programmerUnit.isOutsideProgrammingArea(draggingWidget)) {
deleteConnectingWidgets(draggingWidget);
} else {
handlePuzzleMargins();
if(!isValidPlaced(draggingWidget)) {
setConnectingWidgetsToXY(draggingWidget, dragWidgetStartX, dragWidgetStartY);
if(programmerUnit.isOutsideProgrammingArea(draggingWidget)) deleteConnectingWidgets(draggingWidget);
}
}
NetworkHandler.sendToServer(new PacketProgrammerUpdate(te));
TileEntityProgrammer.updatePuzzleConnections(te.progWidgets);
draggingWidget = null;
}
wasClicking = isLeftClicking || isMiddleClicking;
lastMouseX = origX;
lastMouseY = origY;
}
private boolean isValidPlaced(IProgWidget widget1){
Rectangle draggingRect = new Rectangle(widget1.getX(), widget1.getY(), widget1.getWidth() / 2, widget1.getHeight() / 2);
for(IProgWidget widget : te.progWidgets) {
if(widget != widget1) {
if(draggingRect.intersects(widget.getX(), widget.getY(), widget.getWidth() / 2, widget.getHeight() / 2)) {
return false;
}
}
}
IProgWidget[] parameters = widget1.getConnectedParameters();
if(parameters != null) {
for(IProgWidget widget : parameters) {
if(widget != null && !isValidPlaced(widget)) return false;
}
}
IProgWidget outputWidget = widget1.getOutputWidget();
if(outputWidget != null && !isValidPlaced(outputWidget)) return false;
return true;
}
private void handlePuzzleMargins(){
//Check for connection to the left of the dragged widget.
Class<? extends IProgWidget> returnValue = draggingWidget.returnType();
if(returnValue != null) {
for(IProgWidget widget : te.progWidgets) {
if(widget != draggingWidget && Math.abs(widget.getX() + widget.getWidth() / 2 - draggingWidget.getX()) <= FAULT_MARGIN) {
Class<? extends IProgWidget>[] parameters = widget.getParameters();
if(parameters != null) {
for(int i = 0; i < parameters.length; i++) {
if(widget.canSetParameter(i) && parameters[i] == returnValue && Math.abs(widget.getY() + i * 11 - draggingWidget.getY()) <= FAULT_MARGIN) {
setConnectingWidgetsToXY(draggingWidget, widget.getX() + widget.getWidth() / 2, widget.getY() + i * 11);
return;
}
}
}
}
}
}
//check for connection to the right of the dragged widget.
Class<? extends IProgWidget>[] parameters = draggingWidget.getParameters();
if(parameters != null) {
for(IProgWidget widget : te.progWidgets) {
IProgWidget outerPiece = draggingWidget;
if(outerPiece.returnType() != null) {//When the piece is a parameter pice (area, item filter, text).
while(outerPiece.getConnectedParameters()[0] != null) {
outerPiece = outerPiece.getConnectedParameters()[0];
}
}
if(widget != draggingWidget && Math.abs(outerPiece.getX() + outerPiece.getWidth() / 2 - widget.getX()) <= FAULT_MARGIN) {
if(widget.returnType() != null) {
for(int i = 0; i < parameters.length; i++) {
if(draggingWidget.canSetParameter(i) && parameters[i] == widget.returnType() && Math.abs(draggingWidget.getY() + i * 11 - widget.getY()) <= FAULT_MARGIN) {
setConnectingWidgetsToXY(draggingWidget, widget.getX() - draggingWidget.getWidth() / 2 - (outerPiece.getX() - draggingWidget.getX()), widget.getY() - i * 11);
}
}
} else {
Class<? extends IProgWidget>[] checkingPieceParms = widget.getParameters();
if(checkingPieceParms != null) {
for(int i = 0; i < checkingPieceParms.length; i++) {
if(widget.canSetParameter(i + parameters.length) && checkingPieceParms[i] == parameters[0] && Math.abs(widget.getY() + i * 11 - draggingWidget.getY()) <= FAULT_MARGIN) {
setConnectingWidgetsToXY(draggingWidget, widget.getX() - draggingWidget.getWidth() / 2 - (outerPiece.getX() - draggingWidget.getX()), widget.getY() + i * 11);
}
}
}
}
}
}
}
//check for connection to the top of the dragged widget.
if(draggingWidget.hasStepInput()) {
for(IProgWidget widget : te.progWidgets) {
if(widget.hasStepOutput() && Math.abs(widget.getX() - draggingWidget.getX()) <= FAULT_MARGIN && Math.abs(widget.getY() + widget.getHeight() / 2 - draggingWidget.getY()) <= FAULT_MARGIN) {
setConnectingWidgetsToXY(draggingWidget, widget.getX(), widget.getY() + widget.getHeight() / 2);
}
}
}
//check for connection to the bottom of the dragged widget.
if(draggingWidget.hasStepOutput()) {
for(IProgWidget widget : te.progWidgets) {
if(widget.hasStepInput() && Math.abs(widget.getX() - draggingWidget.getX()) <= FAULT_MARGIN && Math.abs(widget.getY() - draggingWidget.getY() - draggingWidget.getHeight() / 2) <= FAULT_MARGIN) {
setConnectingWidgetsToXY(draggingWidget, widget.getX(), widget.getY() - draggingWidget.getHeight() / 2);
}
}
}
}
private void setConnectingWidgetsToXY(IProgWidget widget, int x, int y){
widget.setX(x);
widget.setY(y);
IProgWidget[] connectingWidgets = widget.getConnectedParameters();
if(connectingWidgets != null) {
for(int i = 0; i < connectingWidgets.length; i++) {
if(connectingWidgets[i] != null) {
if(i < connectingWidgets.length / 2) {
setConnectingWidgetsToXY(connectingWidgets[i], x + widget.getWidth() / 2, y + i * 11);
} else {
int totalWidth = 0;
IProgWidget branch = connectingWidgets[i];
while(branch != null) {
totalWidth += branch.getWidth() / 2;
branch = branch.getConnectedParameters()[0];
}
setConnectingWidgetsToXY(connectingWidgets[i], x - totalWidth, y + (i - connectingWidgets.length / 2) * 11);
}
}
}
}
IProgWidget outputWidget = widget.getOutputWidget();
if(outputWidget != null) setConnectingWidgetsToXY(outputWidget, x, y + widget.getHeight() / 2);
}
private void copyAndConnectConnectingWidgets(IProgWidget original, IProgWidget copy){
IProgWidget[] connectingWidgets = original.getConnectedParameters();
if(connectingWidgets != null) {
for(int i = 0; i < connectingWidgets.length; i++) {
if(connectingWidgets[i] != null) {
IProgWidget c = connectingWidgets[i].copy();
te.progWidgets.add(c);
copy.setParameter(i, c);
copyAndConnectConnectingWidgets(connectingWidgets[i], c);
}
}
}
IProgWidget outputWidget = original.getOutputWidget();
if(outputWidget != null) {
IProgWidget c = outputWidget.copy();
te.progWidgets.add(c);
copy.setOutputWidget(c);
copyAndConnectConnectingWidgets(outputWidget, c);
}
}
private void deleteConnectingWidgets(IProgWidget widget){
te.progWidgets.remove(widget);
IProgWidget[] connectingWidgets = widget.getConnectedParameters();
if(connectingWidgets != null) {
for(IProgWidget widg : connectingWidgets) {
if(widg != null) deleteConnectingWidgets(widg);
}
}
IProgWidget outputWidget = widget.getOutputWidget();
if(outputWidget != null) deleteConnectingWidgets(outputWidget);
}
/**
* Fired when a control is clicked. This is the equivalent of
* ActionListener.actionPerformed(ActionEvent e).
*/
@Override
protected void actionPerformed(GuiButton button){
switch(button.id){
case 0:// redstone button
// redstoneBehaviourStat.closeWindow();
break;
case 3:
if(--widgetPage < 0) widgetPage = maxPage;
updateVisibleProgWidgets();
return;
case 4:
if(++widgetPage > maxPage) widgetPage = 0;
updateVisibleProgWidgets();
return;
case 5:
for(IProgWidget widget : te.progWidgets) {
if(widget instanceof ProgWidgetStart) {
programmerUnit.gotoPiece(widget);
break;
}
}
return;
case 6:
if(te.progWidgets.size() > 0) {
programmerUnit.gotoPiece(te.progWidgets.get(te.progWidgets.size() - 1));
}
return;
case 7:
NBTTagCompound mainTag = new NBTTagCompound();
te.writeProgWidgetsToNBT(mainTag);
FMLClientHandler.instance().showGuiScreen(pastebinGui = new GuiPastebin(this, mainTag));
break;
case 11:
te.progWidgets.clear();
NetworkHandler.sendToServer(new PacketProgrammerUpdate(te));
break;
case 12:
for(IProgWidget widget : te.progWidgets) {
if(widget instanceof ProgWidgetStart) {
generateRelativeOperators((ProgWidgetCoordinateOperator)widget.getOutputWidget(), null, false);
break;
}
}
break;
}
NetworkHandler.sendToServer(new PacketGuiButton(button.id));
}
private void toggleShowWidgets(){
showingAllWidgets = !showingAllWidgets;
allWidgetsButton.displayString = showingAllWidgets ? ">" : "<";
updateVisibleProgWidgets();
}
@Override
public void actionPerformed(IGuiWidget button){
if(button == allWidgetsButton) {
toggleShowWidgets();
} else {
for(int i = 0; i < difficultyButtons.size(); i++) {
if(difficultyButtons.get(i).checked) {
Config.setProgrammerDifficulty(i);
break;
}
}
if(showingAllWidgets) {
toggleShowWidgets();
}
updateVisibleProgWidgets();
}
}
@Override
public void updateScreen(){
super.updateScreen();
undoButton.enabled = te.canUndo;
redoButton.enabled = te.canRedo;
updateConvertRelativeState();
ItemStack programmedItem = te.getStackInSlot(TileEntityProgrammer.PROGRAM_SLOT);
oldShowingWidgetProgress = showingWidgetProgress;
if(showingAllWidgets) {
int maxProgress = maxPage * 22;
if(showingWidgetProgress < maxProgress) {
showingWidgetProgress += 30;
if(showingWidgetProgress >= maxProgress) {
showingWidgetProgress = maxProgress;
updateVisibleProgWidgets();
}
}
} else {
showingWidgetProgress -= 30;
if(showingWidgetProgress < 0) showingWidgetProgress = 0;
}
List<String> errors = new ArrayList<String>();
List<String> warnings = new ArrayList<String>();
for(IProgWidget w : te.progWidgets) {
w.addErrors(errors, te.progWidgets);
w.addWarnings(warnings, te.progWidgets);
}
boolean isDeviceInserted = programmedItem != null;
importButton.enabled = isDeviceInserted;
exportButton.enabled = isDeviceInserted && errors.size() == 0;
List<String> exportButtonTooltip = new ArrayList<String>();
exportButtonTooltip.add("Export program");
exportButtonTooltip.add(I18n.format("gui.programmer.button.export.programmingWhen", I18n.format("gui.programmer.button.export." + (te.redstoneMode == 0 ? "pressingButton" : "onItemInsert"))));
exportButtonTooltip.add(I18n.format("gui.programmer.button.export.pressRToChange"));
if(programmedItem != null) {
List<ItemStack> requiredPieces = te.getRequiredPuzzleStacks();
List<ItemStack> returnedPieces = te.getReturnedPuzzleStacks();
if(!requiredPieces.isEmpty() || !returnedPieces.isEmpty()) exportButtonTooltip.add("");
if(!requiredPieces.isEmpty()) {
exportButtonTooltip.add("Required Programming Puzzles:");
if(player.capabilities.isCreativeMode) exportButtonTooltip.add("(Creative mode, so the following is free)");
for(ItemStack stack : requiredPieces) {
String prefix;
if(te.hasEnoughPuzzleStacks(player, stack)) {
prefix = EnumChatFormatting.GREEN.toString();
} else {
prefix = EnumChatFormatting.RED.toString();
exportButton.enabled = player.capabilities.isCreativeMode && errors.size() == 0;
}
exportButtonTooltip.add(prefix + "-" + stack.stackSize + "x " + stack.getDisplayName());
}
}
if(!returnedPieces.isEmpty()) {
exportButtonTooltip.add("Returned Programming Puzzles:");
if(player.capabilities.isCreativeMode) exportButtonTooltip.add("(Creative mode, nothing's given)");
for(ItemStack stack : returnedPieces) {
exportButtonTooltip.add("-" + stack.stackSize + "x " + stack.getDisplayName());
}
}
} else {
exportButtonTooltip.add("No programmable item inserted.");
}
if(errors.size() > 0) exportButtonTooltip.add(EnumChatFormatting.RED + I18n.format("gui.programmer.errorCount", errors.size()));
if(warnings.size() > 0) exportButtonTooltip.add(EnumChatFormatting.YELLOW + I18n.format("gui.programmer.warningCount", warnings.size()));
exportButton.setTooltipText(exportButtonTooltip);
if(programmedItem != null) {
nameField.setEnabled(true);
if(!nameField.isFocused()) {
if(wasFocused) {
programmedItem.setStackDisplayName(nameField.getText());
NetworkHandler.sendToServer(new PacketUpdateTextfield(te, 0));
}
nameField.setText(programmedItem.getDisplayName());
wasFocused = false;
} else {
wasFocused = true;
}
} else {
nameField.setEnabled(false);
nameField.setText("");
wasFocused = false;
}
}
private void updateConvertRelativeState(){
convertToRelativeButton.enabled = false;
List<String> tooltip = new ArrayList<String>();
tooltip.add("gui.programmer.button.convertToRelative.desc");
boolean startFound = false;
for(IProgWidget startWidget : te.progWidgets) {
if(startWidget instanceof ProgWidgetStart) {
startFound = true;
IProgWidget widget = startWidget.getOutputWidget();
if(widget instanceof ProgWidgetCoordinateOperator) {
ProgWidgetCoordinateOperator operatorWidget = (ProgWidgetCoordinateOperator)widget;
if(!operatorWidget.getVariable().equals("")) {
try {
if(generateRelativeOperators(operatorWidget, tooltip, true)) {
convertToRelativeButton.enabled = true;
} else {
tooltip.add("gui.programmer.button.convertToRelative.notEnoughRoom");
}
} catch(NullPointerException e) {
tooltip.add("gui.programmer.button.convertToRelative.cantHaveVariables");
}
} else {
tooltip.add("gui.programmer.button.convertToRelative.noVariableName");
}
} else {
tooltip.add("gui.programmer.button.convertToRelative.noBaseCoordinate");
}
}
}
if(!startFound) tooltip.add("gui.programmer.button.convertToRelative.noStartPiece");
List<String> localizedTooltip = new ArrayList<String>();
for(String s : tooltip) {
localizedTooltip.addAll(PneumaticCraftUtils.convertStringIntoList(I18n.format(s), 40));
}
convertToRelativeButton.setTooltipText(localizedTooltip);
}
/**
*
* @param baseWidget
* @param simulate
* @return true if successful
*/
private boolean generateRelativeOperators(ProgWidgetCoordinateOperator baseWidget, List<String> tooltip, boolean simulate){
ChunkPosition baseCoord = ProgWidgetCoordinateOperator.calculateCoordinate(baseWidget, 0, baseWidget.getOperator());
Map<ChunkPosition, String> offsetToVariableNames = new HashMap<ChunkPosition, String>();
for(IProgWidget widget : te.progWidgets) {
if(widget instanceof ProgWidgetArea) {
ProgWidgetArea area = (ProgWidgetArea)widget;
if(area.getCoord1Variable().equals("") && (area.x1 != 0 || area.y1 != 0 || area.z1 != 0)) {
ChunkPosition offset = new ChunkPosition(area.x1 - baseCoord.chunkPosX, area.y1 - baseCoord.chunkPosY, area.z1 - baseCoord.chunkPosZ);
String var = getOffsetVariable(offsetToVariableNames, baseWidget.getVariable(), offset);
if(!simulate) area.setCoord1Variable(var);
}
if(area.getCoord2Variable().equals("") && (area.x2 != 0 || area.y2 != 0 || area.z2 != 0)) {
ChunkPosition offset = new ChunkPosition(area.x2 - baseCoord.chunkPosX, area.y2 - baseCoord.chunkPosY, area.z2 - baseCoord.chunkPosZ);
String var = getOffsetVariable(offsetToVariableNames, baseWidget.getVariable(), offset);
if(!simulate) area.setCoord2Variable(var);
}
} else if(widget instanceof ProgWidgetCoordinate && baseWidget.getConnectedParameters()[0] != widget) {
ProgWidgetCoordinate coordinate = (ProgWidgetCoordinate)widget;
if(!coordinate.isUsingVariable()) {
ChunkPosition c = coordinate.getCoordinate();
String chunkString = "(" + c.chunkPosX + ", " + c.chunkPosY + ", " + c.chunkPosZ + ")";
if(PneumaticCraftUtils.distBetween(c, 0, 0, 0) < 64) { //When the coordinate value is close to 0, there's a low chance it means a position, and rather an offset.
if(tooltip != null) tooltip.add(I18n.format("gui.programmer.button.convertToRelative.coordIsNotChangedWarning", chunkString));
} else {
if(tooltip != null) tooltip.add(I18n.format("gui.programmer.button.convertToRelative.coordIsChangedWarning", chunkString));
if(!simulate) {
ChunkPosition offset = new ChunkPosition(c.chunkPosX - baseCoord.chunkPosX, c.chunkPosY - baseCoord.chunkPosY, c.chunkPosZ - baseCoord.chunkPosZ);
String var = getOffsetVariable(offsetToVariableNames, baseWidget.getVariable(), offset);
if(!simulate) {
coordinate.setVariable(var);
coordinate.setUsingVariable(true);
}
}
}
}
}
}
if(offsetToVariableNames.size() > 0) {
ProgWidgetCoordinateOperator firstOperator = null;
ProgWidgetCoordinateOperator prevOperator = baseWidget;
int x = baseWidget.getX();
for(Map.Entry<ChunkPosition, String> entry : offsetToVariableNames.entrySet()) {
ProgWidgetCoordinateOperator operator = new ProgWidgetCoordinateOperator();
operator.setVariable(entry.getValue());
int y = prevOperator.getY() + prevOperator.getHeight() / 2;
operator.setX(x);
operator.setY(y);
if(!isValidPlaced(operator)) return false;
ProgWidgetCoordinate coordinatePiece1 = new ProgWidgetCoordinate();
coordinatePiece1.setX(x + prevOperator.getWidth() / 2);
coordinatePiece1.setY(y);
coordinatePiece1.setVariable(baseWidget.getVariable());
coordinatePiece1.setUsingVariable(true);
if(!isValidPlaced(coordinatePiece1)) return false;
ProgWidgetCoordinate coordinatePiece2 = new ProgWidgetCoordinate();
coordinatePiece2.setX(x + prevOperator.getWidth() / 2 + coordinatePiece1.getWidth() / 2);
coordinatePiece2.setY(y);
coordinatePiece2.setCoordinate(entry.getKey());
if(!isValidPlaced(coordinatePiece2)) return false;
if(!simulate) {
te.progWidgets.add(operator);
te.progWidgets.add(coordinatePiece1);
te.progWidgets.add(coordinatePiece2);
}
if(firstOperator == null) firstOperator = operator;
prevOperator = operator;
}
if(!simulate) {
NetworkHandler.sendToServer(new PacketProgrammerUpdate(te));
TileEntityProgrammer.updatePuzzleConnections(te.progWidgets);
}
return true;
} else {
return true; //When there's nothing to place there's always room.
}
}
private String getOffsetVariable(Map<ChunkPosition, String> offsetToVariableNames, String baseVariable, ChunkPosition offset){
if(offset.equals(new ChunkPosition(0, 0, 0))) return baseVariable;
String var = offsetToVariableNames.get(offset);
if(var == null) {
var = "var" + (offsetToVariableNames.size() + 1);
offsetToVariableNames.put(offset, var);
}
return var;
}
@Override
protected void mouseClicked(int x, int y, int par3){
ItemStack programmedItem = te.getStackInSlot(TileEntityProgrammer.PROGRAM_SLOT);
if(nameField.isFocused() && programmedItem != null) {
programmedItem.setStackDisplayName(nameField.getText());
NetworkHandler.sendToServer(new PacketUpdateTextfield(te, 0));
}
super.mouseClicked(x, y, par3);
if(par3 == 1 && showingWidgetProgress == 0) {
IProgWidget widget = programmerUnit.getHoveredWidget(x, y);
if(widget != null) {
GuiScreen screen = widget.getOptionWindow(this);
if(screen != null) mc.displayGuiScreen(screen);
}
}
}
@Override
public void onGuiClosed(){
te.translatedX = programmerUnit.getTranslatedX();
te.translatedY = programmerUnit.getTranslatedY();
te.zoomState = programmerUnit.getLastZoom();
te.showFlow = showFlow.checked;
te.showInfo = showInfo.checked;
super.onGuiClosed();
}
@Override
@Optional.Method(modid = ModIds.NEI)
public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility){
currentVisibility.showNEI = false;
return currentVisibility;
}
}