package mods.ocminecart.client.gui;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.ItemPanel;
import codechicken.nei.LayoutManager;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.Optional;
import li.cil.oc.api.internal.TextBuffer;
import li.cil.oc.api.network.ManagedEnvironment;
import li.cil.oc.client.KeyBindings;
import li.cil.oc.client.renderer.TextBufferRenderCache;
import li.cil.oc.client.renderer.gui.BufferRenderer;
import mods.ocminecart.OCMinecart;
import mods.ocminecart.Settings;
import mods.ocminecart.client.SlotIcons;
import mods.ocminecart.client.gui.widget.EnergyBar;
import mods.ocminecart.client.gui.widget.GuiUtil;
import mods.ocminecart.client.gui.widget.ImageButton;
import mods.ocminecart.client.gui.widget.SliderButton;
import mods.ocminecart.common.container.ComputerCartContainer;
import mods.ocminecart.common.container.slots.ContainerSlot;
import mods.ocminecart.common.inventory.ComponetInventory;
import mods.ocminecart.common.minecart.ComputerCart;
import mods.ocminecart.interaction.NEI;
import mods.ocminecart.network.ModNetwork;
import mods.ocminecart.network.message.GuiButtonClick;
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.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IIcon;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import java.util.*;
import java.util.Map.Entry;
//I used the code from OpenComputer's Robot GUI to make this class (ImageButton, Buffer renderer, Mouse & Keyboard handler, ...)
//Credits to Sangar
public class ComputerCartGui extends GuiContainer {
//Resources
private ResourceLocation textureNoScreen = new ResourceLocation( Settings.OC_ResLoc , "textures/gui/robot_noscreen.png");
private ResourceLocation textureScreen = new ResourceLocation( Settings.OC_ResLoc , "textures/gui/robot.png");
private ResourceLocation textureOnOffButton = new ResourceLocation( Settings.OC_ResLoc , "textures/gui/button_power.png");
private ResourceLocation ebar = new ResourceLocation( Settings.OC_ResLoc , "textures/gui/bar.png");
private ResourceLocation selection = new ResourceLocation( Settings.OC_ResLoc , "textures/gui/robot_selection.png");
//Container (as instance of ComputerCartContainer)
private ComputerCartContainer container;
//Textbuffer and keyboard
private int txtWidth, txtHeight;
private double maxBufferWidth = 240.0;
private double maxBufferHeight = 140.0;
private double bufferscale = 0.0;
private double bufferRenderWidth = Math.min(maxBufferWidth, TextBufferRenderCache.renderer().charRenderWidth() * 50);
private double bufferRenderHeight = Math.min(maxBufferHeight, TextBufferRenderCache.renderer().charRenderHeight() * 16);
private int bufferX = (int)(8 + (this.maxBufferWidth - this.bufferRenderWidth) /2);
private int bufferY = (int)(8 + (this.maxBufferHeight - this.bufferRenderHeight) /2);
private TextBuffer textbuffer;
private boolean hasKeyboard=false;
private Map<Integer, Character> pressedKeys = new HashMap<Integer, Character>();
//Other stuff
private ImageButton btPower;
private Slot hoveredSlot = null;
private ItemStack hoveredNEI = null;
private SliderButton invslider = null;
private boolean[] disSlot = new boolean[16];
private int offset = 0;
//-------Init functions-------//
public ComputerCartGui(InventoryPlayer inventory, ComputerCart entity) {
super(new ComputerCartContainer(inventory,entity));
this.container=(ComputerCartContainer) this.inventorySlots;
this.initComponents(entity.compinv);
this.ySize= (container.getHasScreen()) ? ComputerCartContainer.YSIZE_SCR : ComputerCartContainer.YSIZE_NOSCR;
this.xSize= ComputerCartContainer.XSIZE;
this.offset = (this.textbuffer!=null) ? ComputerCartContainer.DELTA : 0;
this.invslider= new SliderButton(244,8 + offset, 6, 13, 94);
}
//Initialize components. get Screen and check if there is a Keyboard
private void initComponents(ComponetInventory compinv){
Iterator<ManagedEnvironment> list = compinv.getComponents().iterator();
while(list.hasNext()){
ManagedEnvironment env = list.next();
if(env instanceof TextBuffer) this.textbuffer = (TextBuffer) env;
else if(env instanceof li.cil.oc.server.component.Keyboard) this.hasKeyboard = true;
}
}
public void initGui(){
super.initGui();
this.updateSlots();
BufferRenderer.init(Minecraft.getMinecraft().renderEngine);
boolean guiSizeChange = true;
this.txtHeight = (this.textbuffer!=null) ? this.textbuffer.getHeight() : 0;
this.txtWidth = (this.textbuffer!=null) ? this.textbuffer.getWidth() : 0;
BufferRenderer.compileBackground((int)this.bufferRenderWidth, (int)this.bufferRenderHeight, true);
this.btPower = new ImageButton(0, this.guiLeft+5, 5+this.guiTop+offset, 18, 18, null, textureOnOffButton, true);
this.buttonList.add(this.btPower);
Keyboard.enableRepeatEvents(true);
}
@Override
public boolean doesGuiPauseGame(){
return false;
}
//-------Override render functions-------//
@Override
protected void drawGuiContainerBackgroundLayer(float p_146976_1_, int p_146976_2_, int p_146976_3_) {
GL11.glColor3d(1F, 1F, 1F);
Minecraft.getMinecraft().getTextureManager().bindTexture((container.getHasScreen())? textureScreen : textureNoScreen );
this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize);
this.renderGuiSlots();
}
@Override
protected void drawGuiContainerForegroundLayer(int mx, int my) {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
if(this.container.getHasScreen() && this.textbuffer!=null){
this.drawBufferLayer();
double bw = this.txtWidth * TextBufferRenderCache.renderer().charRenderWidth();
double bh = this.txtHeight * TextBufferRenderCache.renderer().charRenderHeight();
double scaleX = Math.min(this.bufferRenderWidth / bw , 1);
double scaleY = Math.min(this.bufferRenderHeight / bh , 1);
this.bufferscale = Math.min(scaleX, scaleY);
}
//Widgets
EnergyBar.drawBar(26, 8 + offset, 12, 140, 150, (double)this.container.sEnergy / (double)this.container.smaxEnergy, ebar);
this.invslider.drawSlider(this.zLevel, this.invslider.getAktive() || this.invslider.isMouseHoverButton(mx - this.guiLeft, my - this.guiTop));
//Highlight
Iterator<Slot> list = this.container.inventorySlots.iterator();
while(list.hasNext()) this.drawSlotHighlight(list.next());
//Render selected slot
if(this.container.sizeinv > 0)
this.drawSelection();
//Tooltips
if(this.func_146978_c(this.btPower.xPosition, this.btPower.yPosition, 18, 18, mx+this.guiLeft, my+this.guiTop)){
List<String> ls = new ArrayList<String>();
if(this.container.getEntity().getRunning()){
ls.add(StatCollector.translateToLocal("tooltip."+OCMinecart.MODID+".gui.turnoff"));
}
else{
ls.add(StatCollector.translateToLocal("tooltip."+OCMinecart.MODID+".gui.turnon"));
ls.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("tooltip."+OCMinecart.MODID+".gui.useanalyzer"));
}
GuiUtil.drawHoverText(ls, mx - this.guiLeft, my - this.guiTop, this.width, this.height, this.guiLeft, Minecraft.getMinecraft().fontRenderer);
}
if(this.func_146978_c(26+this.guiLeft, 8+this.guiTop+offset, 140, 12, mx+this.guiLeft, my+this.guiTop)){
List<String> ls = new ArrayList<String>();
int per = (int)(((double)this.container.sEnergy / (double)this.container.smaxEnergy)*100);
ls.add("Energy: "+per+"% ("+this.container.sEnergy+" / "+this.container.smaxEnergy+")");
GuiUtil.drawHoverText(ls, mx - this.guiLeft, my - this.guiTop, this.width, this.height, this.guiLeft, Minecraft.getMinecraft().fontRenderer);
}
GL11.glPopAttrib();
}
public void drawScreen(int mx, int my, float dt){
this.hoveredSlot=null;
Iterator<Slot> list = this.container.inventorySlots.iterator();
while(list.hasNext()){
Slot slot = list.next();
if(slot!=null){
if(this.func_146978_c(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, mx, my))
this.hoveredSlot = slot;
}
}
this.hoveredNEI = NEI.hoveredStack(this, mx, my);
super.drawScreen(mx, my, dt);
if (Loader.isModLoaded("NotEnoughItems")) {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
this.drawNEIHighlight();
GL11.glPopAttrib();
}
}
//-------Events-------//
protected void actionPerformed(GuiButton button) {
switch(button.id){
case 0:
ModNetwork.channel.sendToServer(GuiButtonClick.entityButtonClick(this.container.getEntity(),0,1));
break;
}
}
public void updateScreen(){
if(this.container.getEntity().getRunning() != btPower.getToggle()) btPower.setToggle(this.container.getEntity().getRunning());
if(this.container.updatesize){
this.invslider.scrollTo(0);
this.invslider.setMaxsteps(this.container.sizeinv / 4 - 4);
this.container.updatesize=false;
}
if(this.invslider.hasUpdate()){
this.invslider.doneUpdate();
this.updateSlots();
}
}
protected void mouseClicked(int x, int y, int button) {
super.mouseClicked(x, y, button);
boolean isMiddleMouseButton = button == 2;
boolean isBoundMouseButton = KeyBindings.isPastingClipboard();
if (this.textbuffer != null && (isMiddleMouseButton || isBoundMouseButton)) {
if (this.hasKeyboard) {
this.textbuffer.clipboard(GuiScreen.getClipboardString(), null);
}
}
else if(button==0){
if(this.invslider.isMouseHoverBox(x - this.guiLeft, y - this.guiTop))
this.invslider.setAktive(true);
}
}
protected void mouseMovedOrUp(int x, int y, int button){
super.mouseMovedOrUp(x, y, button);
if(button == 0 && this.invslider.getAktive()){
this.invslider.setAktive(false);
}
}
public void handleMouseInput() {
super.handleMouseInput();
if (Mouse.hasWheel() && Mouse.getEventDWheel() != 0) {
int mouseX = Mouse.getEventX() * width / mc.displayWidth - guiLeft;
int mouseY = height - Mouse.getEventY() * height / mc.displayHeight - 1 - guiTop;
if (isCoordinateOverInventory(mouseX, mouseY) ||
invslider.isMouseHoverBox(mouseX, mouseY)) {
if (Math.signum(Mouse.getEventDWheel()) < 0) invslider.scrollDown();
else invslider.scrollUp();
}
}
}
protected void mouseClickMove(int x, int y, int button, long time){
super.mouseClickMove(x, y, button, time);
if(this.invslider.getAktive()){
this.invslider.scrollMouse(y - this.guiTop);
}
}
public void handleKeyboardInput() {
if (NEI.isInputFocused()) return;
int code = Keyboard.getEventKey();
if (this.textbuffer != null && code != Keyboard.KEY_ESCAPE && code != Keyboard.KEY_F11) {
if (this.hasKeyboard) {
if (Keyboard.getEventKeyState()) {
char ch = Keyboard.getEventCharacter();
if (!pressedKeys.containsKey(code) || !ignoreRepeat(ch, code)) {
this.textbuffer.keyDown(ch, code, null);
pressedKeys.put(code, ch);
}
}
else{
if(pressedKeys.containsKey(code)){
this.textbuffer.keyUp(pressedKeys.remove(code), code, null);
}
}
if (KeyBindings.isPastingClipboard()) {
this.textbuffer.clipboard(GuiScreen.getClipboardString(), null);
}
}
}
else super.handleKeyboardInput();
}
public void onGuiClosed(){
super.onGuiClosed();
if (this.textbuffer != null)
for(Entry<Integer, Character> e : pressedKeys.entrySet()) {
this.textbuffer.keyUp(e.getValue(), e.getKey(), null);
}
Keyboard.enableRepeatEvents(false);
}
private boolean isCoordinateOverInventory(int x, int y){
return x >= 170 && x < 240 && y >= 8 + offset && y < 78 + offset;
}
private void updateSlots(){
Iterator<Slot> slots = this.container.inventorySlots.iterator();
while(slots.hasNext()){
Slot s = slots.next();
int index = s.getSlotIndex() - this.invslider.getScroll() * 4;
if(s.inventory.equals(this.container.getEntity().maininv)){
if(index>=0 && index < 16 && s.getSlotIndex() < this.container.sizeinv){
s.xDisplayPosition = 170 + (index % 4) * 18;
s.yDisplayPosition = 8 + offset + (index / 4) * 18;
this.disSlot[index] = false;
}
else{
s.xDisplayPosition = -10000;
s.yDisplayPosition = -10000;
if(index>=0 && index < 16) this.disSlot[index] = true;
}
}
}
}
//-------Render functions----------//
//Fuction from OC. used in handleKeyboardInput()
private boolean ignoreRepeat(char ch, int code) {
return code == Keyboard.KEY_LCONTROL ||
code == Keyboard.KEY_RCONTROL ||
code == Keyboard.KEY_LMENU ||
code == Keyboard.KEY_RMENU ||
code == Keyboard.KEY_LSHIFT ||
code == Keyboard.KEY_RSHIFT ||
code == Keyboard.KEY_LMETA ||
code == Keyboard.KEY_RMETA;
}
//Render the Highlight for Components
protected void drawSlotHighlight(Slot slot) {
if(Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null){
boolean highlight = false;
if(!(slot instanceof ContainerSlot) || (((ContainerSlot)slot).getSlotType() != "none" && ((ContainerSlot)slot).getTier() != -1)){
boolean inPlayerInv = slot.inventory == Minecraft.getMinecraft().thePlayer.inventory;
if(this.hoveredSlot!=null){
if(this.hoveredSlot.getHasStack() && (slot instanceof ContainerSlot) && slot.isItemValid(this.hoveredSlot.getStack())) highlight=true;
else if(slot.getHasStack() && (this.hoveredSlot instanceof ContainerSlot) && this.hoveredSlot.isItemValid(slot.getStack()))
highlight=true;
}
else{
if(this.hoveredNEI!=null && (slot instanceof ContainerSlot) && slot.isItemValid(this.hoveredNEI)){
highlight=true;
}
}
}
if(highlight){
this.zLevel += 100;
this.drawGradientRect(slot.xDisplayPosition, slot.yDisplayPosition, slot.xDisplayPosition + 16, slot.yDisplayPosition + 16, 0x80FFFFFF, 0x80FFFFFF);
this.zLevel -= 100;
}
}
}
//Render the Highlight for NEI Slots
@Optional.Method(modid = "NotEnoughItems")
private void drawNEIHighlight(){
ItemPanel panel = LayoutManager.itemPanel;
if(panel == null) return;
this.zLevel += 350;
for(int i=0;i<ItemPanel.items.size();i+=1){
Rectangle4i rect = panel.getSlotRect(i);
ItemStack slot = panel.getStackMouseOver(rect.x, rect.y);
if(slot!=null && this.hoveredSlot!=null){
if((this.hoveredSlot.inventory != Minecraft.getMinecraft().thePlayer.inventory) && (this.hoveredSlot instanceof ContainerSlot) && this.hoveredSlot.isItemValid(slot)){
drawGradientRect( rect.x1() + 1, rect.y1() + 1, rect.x2(), rect.y2(), 0x40FFFFFF, 0x40FFFFFF);
}
}
}
this.zLevel -= 350;
}
//Draw Screen if there is one
private void drawBufferLayer(){
GL11.glPushMatrix();
GL11.glTranslatef(bufferX, bufferY, 0);
Minecraft.getMinecraft().entityRenderer.disableLightmap(0);
RenderHelper.disableStandardItemLighting();
GL11.glPushMatrix();
GL11.glTranslatef(-3, -3, 0);
GL11.glColor4f(1, 1, 1, 1);
BufferRenderer.drawBackground();
GL11.glPopMatrix();
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
double scaleX = bufferRenderWidth / this.textbuffer.renderWidth();
double scaleY = bufferRenderHeight / this.textbuffer.renderHeight();
double scale = Math.min(scaleX, scaleY);
if (scaleX > scale) {
GL11.glTranslated(this.textbuffer.renderWidth() * (scaleX - scale) / 2, 0, 0);
}
else if (scaleY > scale) {
GL11.glTranslated(0,this.textbuffer.renderHeight() * (scaleY - scale) / 2, 0);
}
GL11.glScaled(scale, scale, scale);
GL11.glScaled(this.bufferscale, this.bufferscale, 1);
BufferRenderer.drawText(this.textbuffer);
RenderHelper.enableStandardItemLighting();
GL11.glDisable(GL11.GL_BLEND);
GL11.glPopMatrix();
}
//Render the Background Icons
private void renderGuiSlots(){
Iterator<Slot> list = this.container.inventorySlots.iterator();
this.mc.getTextureManager().bindTexture(TextureMap.locationItemsTexture);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glDisable(GL11.GL_LIGHTING);
IIcon non = SlotIcons.fromTier(-1);
this.drawTexturedModelRectFromIcon(this.guiLeft+170, this.guiTop+84+offset, non, 16, 16);
//Render the Icons for Container Slots
while(list.hasNext()){
Slot slot = list.next();
if(slot instanceof ContainerSlot){
IIcon typeicon = SlotIcons.fromSlot(((ContainerSlot) slot).getSlotType());
if(typeicon!=null) this.drawTexturedModelRectFromIcon(this.guiLeft+slot.xDisplayPosition,this.guiTop+slot.yDisplayPosition, typeicon, 16, 16);
}
}
//Render Icons for disabled Inventory Slots
for(int i=0;i<4;i+=1){
for(int j=0;j<4;j+=1){
int xpos = this.guiLeft + 170 + i * 18;
int ypos = this.guiTop + 8 + offset + j * 18;
if(this.disSlot[i*j]){
this.drawTexturedModelRectFromIcon(xpos,ypos, SlotIcons.fromTier(-1), 16, 16);
}
}
}
}
private void drawSelection() {
int slot = this.container.selSlot - this.invslider.getScroll() * 4;
if (slot >= 0 && slot < 16) {
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
RenderHelper.disableStandardItemLighting();
Minecraft.getMinecraft().renderEngine.bindTexture(selection);
double now = System.currentTimeMillis() / 1000.0;
double offsetV = (int)((now % 1) * 17) / 17D;
int x = 168 + (slot % 4) * (18);
int y = 6 + offset + (slot / 4) * (18);
//OCMinecart.logger.info(x+" : "+y);
Tessellator t = Tessellator.instance;
t.startDrawingQuads();
t.addVertexWithUV(x, y, zLevel, 0, offsetV);
t.addVertexWithUV(x, y + 20, zLevel, 0, offsetV + 1D/17D);
t.addVertexWithUV(x + 20, y + 20, zLevel, 1, offsetV + 1D/17D);
t.addVertexWithUV(x + 20, y, zLevel, 1, offsetV);
t.draw();
RenderHelper.enableStandardItemLighting();
GL11.glDisable(GL11.GL_BLEND);
}
}
}