org.spoutcraft.client.gui.mainmenu.MainMenu.java Source code

Java tutorial

Introduction

Here is the source code for org.spoutcraft.client.gui.mainmenu.MainMenu.java

Source

/*
 * This file is part of Spoutcraft.
 *
 * Copyright (c) 2011 Spout LLC <http://www.spout.org/>
 * Spoutcraft is licensed under the GNU Lesser General Public License.
 *
 * Spoutcraft is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Spoutcraft is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.spoutcraft.client.gui.mainmenu;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;

import org.apache.commons.io.FileUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;

import net.minecraft.src.GuiIngameMenu;
import net.minecraft.src.GuiScreen;
import net.minecraft.src.GuiSelectWorld;
import net.minecraft.src.StringTranslate;

import org.bukkit.ChatColor;

import org.spoutcraft.api.Spoutcraft;
import org.spoutcraft.api.gui.Button;
import org.spoutcraft.api.gui.Color;
import org.spoutcraft.api.gui.GenericButton;
import org.spoutcraft.api.gui.GenericLabel;
import org.spoutcraft.api.gui.GenericTexture;
import org.spoutcraft.api.gui.Label;
import org.spoutcraft.api.gui.RenderPriority;
import org.spoutcraft.api.gui.RenderUtil;
import org.spoutcraft.api.gui.Texture;
import org.spoutcraft.api.gui.WidgetAnchor;
import org.spoutcraft.client.SpoutClient;
import org.spoutcraft.client.config.Configuration;
import org.spoutcraft.client.gui.MCRenderDelegate;
import org.spoutcraft.client.gui.settings.GuiSimpleOptions;
import org.spoutcraft.client.io.CustomTextureManager;
import org.spoutcraft.client.io.FileUtil;
import org.spoutcraft.client.special.Holiday;
import org.spoutcraft.client.special.Resources;

public class MainMenu extends GuiScreen {
    public static String mcVersion = "Unknown Version";
    final static List<String> splashes = new ArrayList<String>(1000);
    public static boolean hasLoaded = false;
    Button singleplayer, multiplayer, textures, about, options, quit, language;
    Texture background, logo;
    Label splashText, buildNumber, animate, debugText;
    static String timeOfDay = "";
    final static List<String> backgrounds = new ArrayList<String>();
    // Animate click delay
    private static final int CLICK_DELAY = 50;
    int clickDelay = 0;
    // Debug
    long lastTime = System.currentTimeMillis();
    int lastFPS = 0;
    int fpsDelay = 1;
    int poorFPSCount = 0;

    public MainMenu() {
        splashText = new GenericLabel(getSplashText());
        updateBackgrounds();

        Holiday holiday = Resources.getHoliday();
        if (holiday != null) {
            splashText.setText(holiday.getSplash());
        }

        // Randomize background order
        Random rand = new Random();
        // Randomize by swapping the first background with a random background in the list
        // Repeat sufficient times
        for (int i = 0; i < backgrounds.size() * 2; i++) {
            int newIndex = rand.nextInt(backgrounds.size());
            String temp = backgrounds.get(0);
            backgrounds.set(0, backgrounds.get(newIndex));
            backgrounds.set(newIndex, temp);
        }

        if (backgrounds.size() == 0) {
            System.out.println("Failed to find any backgrounds for " + timeOfDay);
            backgrounds.add("/res/background/day/day1.jpg");
        }

        background = new BackgroundTexture(backgrounds);
    }

    private static void updateBackgrounds() {
        if (!timeOfDay.equals(getTimeFolder())) {
            timeOfDay = getTimeFolder();
        } else {
            return;
        }

        int picture = 1;
        int pass = 0;
        StringBuilder builder = new StringBuilder();
        backgrounds.clear();
        while (true) {
            builder.append("/res/background/");
            builder.append(timeOfDay);
            builder.append("/");
            builder.append(timeOfDay);
            builder.append(picture);
            builder.append(pass == 0 ? ".png" : ".jpg");
            if (CustomTextureManager.getTextureFromJar(builder.toString()) != null) {
                backgrounds.add(builder.toString());
                picture++;
                pass = 0;
            } else if (pass == 0) {
                pass++;
            } else {
                break;
            }
            builder.setLength(0); // Reset
        }
    }

    private static String getSplashText() {
        BufferedReader br = null;
        try {
            if (splashes.isEmpty()) {
                File splashTextFile = new File(FileUtil.getConfigDir(), "splashes.txt");
                // Refresh every day
                if (!splashTextFile.exists() || (System.currentTimeMillis()
                        - splashTextFile.lastModified() > (1L * 24 * 60 * 60 * 1000))) {
                    URL test = new URL("http://cdn.spout.org/splashes.txt");
                    HttpURLConnection urlConnect = (HttpURLConnection) test.openConnection();
                    System.setProperty("http.agent", "");
                    urlConnect.setRequestProperty("User-Agent",
                            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19");

                    File temp = new File(FileUtil.getConfigDir(), "splashes.temp");
                    if (temp.exists()) {
                        temp.delete();
                    }

                    splashTextFile.delete();

                    FileUtils.copyInputStreamToFile(urlConnect.getInputStream(), temp);
                    FileUtils.moveFile(temp, splashTextFile);
                }
                br = new BufferedReader(new FileReader(splashTextFile));
                String line;
                splashes.clear();
                while ((line = br.readLine()) != null) {
                    splashes.add(new String(line.getBytes(), "UTF-8"));
                }
                br.close();
            }
            return splashes.get((new Random()).nextInt(splashes.size()));
        } catch (Exception e) {
            e.printStackTrace();
            return "I <3 Spout's " + e.getMessage();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception ignore) {
                }
            }
        }
    }

    private static String getTimeFolder() {
        int hours = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        if (hours < 6) {
            return "night";
        }
        if (hours < 12) {
            return "day";
        }
        if (hours < 20) {
            return "evening";
        }
        return "night";
    }

    public void initGui() {
        int textWidth;

        StringTranslate translate = StringTranslate.getInstance();

        singleplayer = new GenericButton(translate.translateKey("menu.singleplayer"));
        singleplayer.setGeometry(width - 110, height - 155, 100, 20);

        multiplayer = new GenericButton(translate.translateKey("menu.multiplayer"));
        multiplayer.setGeometry(width - 110, height - 130, 100, 20);

        textures = new GenericButton(translate.translateKey("options.texture.pack"));
        textures.setGeometry(width - 110, height - 105, 100, 20);

        buildNumber = new GenericLabel(SpoutClient.getClientVersion());
        textWidth = Spoutcraft.getRenderDelegate().getMinecraftFont().getTextWidth(buildNumber.getText());
        buildNumber.setTextColor(new Color(0x6CC0DC));
        buildNumber.setGeometry(Math.min(90 - textWidth, width - 296 - textWidth), height - 99, 75, 20);

        about = new GenericButton("About");
        about.setGeometry(Math.min(98, width - 288), height - 105, 51, 20);

        options = new GenericButton(translate.translateKey("menu.options"));
        options.setGeometry(Math.min(159, width - 227), height - 105, 51, 20);

        quit = new GenericButton(translate.translateKey("menu.quit"));
        quit.setGeometry(Math.min(220, width - 166), height - 105, 51, 20);

        background.setGeometry(0, 0, width, height);
        background.setPriority(RenderPriority.Highest);
        background.setAnchor(WidgetAnchor.TOP_LEFT);
        background.setLocal(true);

        splashText.setGeometry(Math.min(100, width - 245), height - 135, 200, 12);
        splashText.setTextColor(new Color(0x6CC0DC));
        textWidth = Spoutcraft.getRenderDelegate().getMinecraftFont().getTextWidth(splashText.getText());
        float scale = ((width - 225F) / textWidth);
        splashText.setScale(Math.min(1.5F, scale));

        logo = new ScaledTexture("/res/logo/spoutcraft.png");
        ((ScaledTexture) logo).setScale(Math.min(1F, (width - 135F) / 256F));
        logo.setGeometry(15, height - 185, 256, 64);
        logo.setLocal(true);
        logo.setDrawAlphaChannel(true);

        animate = new GenericLabel(ChatColor.ITALIC + "Animate");
        textWidth = Spoutcraft.getRenderDelegate().getMinecraftFont().getTextWidth(animate.getText());
        textWidth *= 75;
        textWidth /= 100;
        animate.setGeometry(width - textWidth - 2, height - 8, textWidth, 10);
        animate.setScale(0.75F);
        switch (Configuration.getMainMenuState()) {
        case 1:
            animate.setTextColor(new Color(0x00EE00));
            break;
        case 2:
            animate.setTextColor(new Color(0xFFFF00));
            break;
        case 3:
            animate.setTextColor(new Color(0xFF0000));
            break;
        }

        debugText = new GenericLabel();
        debugText.setTextColor(new Color(0xFFE303));
        debugText.setGeometry(1, 1, 12, 100);
        debugText.setVisible(false);
        this.getScreen().attachWidgets("Spoutcraft", singleplayer, multiplayer, textures, buildNumber, background,
                splashText, about, options, logo, quit, animate, debugText);
    }

    @Override
    public void buttonClicked(Button btn) {
        hasLoaded = true;
        if (singleplayer == btn) {
            mc.displayGuiScreen(new GuiSelectWorld(this));
        }
        if (multiplayer == btn) {
            mc.displayGuiScreen(new org.spoutcraft.client.gui.server.GuiFavorites(this));
        }
        if (textures == btn) {
            mc.displayGuiScreen(new org.spoutcraft.client.gui.texturepacks.GuiTexturePacks());
        }
        if (about == btn) {
            this.mc.displayGuiScreen(new org.spoutcraft.client.gui.about.GuiNewAbout(this));
        }
        if (options == btn) {
            mc.displayGuiScreen(GuiSimpleOptions.constructOptionsScreen(this));
        }
        if (quit == btn) {
            mc.shutdownMinecraftApplet();
        }
    }

    @Override
    public void drawScreen(int mouseX, int mouseY, float scroll) {
        super.drawScreen(mouseX, mouseY, scroll);
        if (Keyboard.isKeyDown(Keyboard.KEY_M)) {
            mc.displayGuiScreen(new org.spoutcraft.client.gui.server.GuiFavorites(this));
        } else if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
            mc.displayGuiScreen(new GuiSelectWorld(this));
        } else if (Keyboard.isKeyDown(Keyboard.KEY_T)) {
            mc.displayGuiScreen(new org.spoutcraft.client.gui.texturepacks.GuiTexturePacks());
        } else if (Keyboard.isKeyDown(Keyboard.KEY_O)) {
            mc.displayGuiScreen(GuiSimpleOptions.constructOptionsScreen(new GuiIngameMenu()));
        }

        long time = System.currentTimeMillis();
        if (fpsDelay > 0) {
            fpsDelay--;
        } else {
            long diff = time - lastTime;
            int fps = (int) (1000 / Math.max(1, diff));
            lastFPS = fps;
            fpsDelay = CLICK_DELAY;
            if (fps < 10) {
                poorFPSCount++;
            } else {
                poorFPSCount = 0;
            }
            if (poorFPSCount > 3) {
                Configuration.setMainMenuState(3);
            }
        }
        lastTime = time;

        debugText.setVisible(false);
        if (Keyboard.isKeyDown(Keyboard.KEY_F3)) {
            debugText.setVisible(true);
            debugText.setText("FPS: " + lastFPS);
        }

        if (clickDelay > 0) {
            clickDelay--;
        }
        if (Mouse.isButtonDown(0) && this.isInBoundingRect(animate, mouseX, mouseY) && clickDelay == 0) {
            Configuration.setMainMenuState(Configuration.getMainMenuState() + 1);
            if (Configuration.getMainMenuState() > 3) {
                Configuration.setMainMenuState(1);
            }
            Configuration.write();
            switch (Configuration.getMainMenuState()) {
            case 1:
                animate.setTextColor(new Color(0x00EE00));
                break;
            case 2:
                animate.setTextColor(new Color(0xFFFF00));
                break;
            case 3:
                animate.setTextColor(new Color(0xFF0000));
                break;
            }
            clickDelay = CLICK_DELAY;
        }

        GL11.glEnable(GL11.GL_BLEND);
    }
}

class ScaledTexture extends GenericTexture {
    float scale;

    ScaledTexture(String path) {
        super(path);
    }

    public ScaledTexture setScale(float scale) {
        this.scale = scale;
        return this;
    }

    @Override
    public void render() {
        GL11.glPushMatrix();
        GL11.glScalef(scale, 1F, 1F);
        super.render();
        GL11.glPopMatrix();
    }
}

class BackgroundTexture extends GenericTexture {
    static final int PAN_TIME = 600;
    static final int EXTRA_PAN_TIME = 150;
    static final int HEIGHT_PERCENT = 70;
    static final int WIDTH_PERCENT = 75;
    final List<String> backgrounds;
    final Random rand = new Random();
    int maxPanTime = PAN_TIME;
    int panTime = PAN_TIME;
    int picture = -1;
    boolean zoomIn = false;

    BackgroundTexture(List<String> backgrounds) {
        super(backgrounds.get(0));
        this.backgrounds = backgrounds;
        cycleBackground();
    }

    public void cycleBackground() {
        picture++;
        if (picture >= backgrounds.size()) {
            picture = 0;
        }
        setUrl(backgrounds.get(picture));
        maxPanTime = PAN_TIME + rand.nextInt(EXTRA_PAN_TIME);
        zoomIn = rand.nextBoolean();
        panTime = zoomIn ? 0 : maxPanTime;
    }

    @Override
    public void render() {
        org.newdawn.slick.opengl.Texture tex = CustomTextureManager.getTextureFromJar(getUrl());
        GL11.glPushMatrix();
        if (tex != null) {
            if (Configuration.getMainMenuState() != 3) {
                animate(tex);
            } else {
                ((MCRenderDelegate) Spoutcraft.getRenderDelegate()).drawTexture(tex, (int) this.getActualWidth(),
                        (int) this.getActualHeight(), white, false, -1, -1, false, GL11.GL_LINEAR);
            }
        } else {
            RenderUtil.drawRectangle(0, 0, (int) getWidth(), (int) getHeight(), 0xff000000);
        }
        GL11.glPopMatrix();
    }

    private static final Color white = new Color(1.0F, 1.0F, 1.0F);

    private void animate(org.newdawn.slick.opengl.Texture tex) {
        int adjustedX = ((100 - HEIGHT_PERCENT) / 2) * tex.getImageHeight() * panTime;
        adjustedX /= maxPanTime;
        adjustedX /= 100;

        int adjustedY = ((100 - WIDTH_PERCENT) / 2) * tex.getImageWidth() * panTime;
        adjustedY /= maxPanTime;
        adjustedY /= 100;

        int adjustedHeight = tex.getImageHeight() - adjustedX;

        int adjustedWidth = tex.getImageWidth() - adjustedY;

        GL11.glScaled(this.getActualWidth() / (adjustedWidth - adjustedX),
                this.getActualHeight() / (adjustedHeight - adjustedY), 1D);
        GL11.glTranslatef(-adjustedX, -adjustedY, 0F);
        ((MCRenderDelegate) Spoutcraft.getRenderDelegate()).drawTexture(tex, adjustedWidth, adjustedHeight, white,
                false, -1, -1, Configuration.getMainMenuState() == 1, GL11.GL_NEAREST);

        if (zoomIn && panTime < maxPanTime) {
            panTime++;
        } else if (!zoomIn && panTime > 0) {
            panTime--;
        } else {
            cycleBackground();
        }
    }
}