a1.Main.java Source code

Java tutorial

Introduction

Here is the source code for a1.Main.java

Source

/*
 * This file is part of the Origin-World game client.
 * Copyright (C) 2012 Arkadiy Fattakhov <ark@ark.su>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package a1;

import a1.dialogs.Dialog;
import a1.dialogs.dlg_Loading;
import a1.dialogs.dlg_Login;
import a1.dialogs.dlg_SysMsg;
import a1.gui.GUI;
import a1.gui.GUI_Debug;
import a1.gui.Skin;
import a1.gui.Skin_MyGUI;
import a1.net.Connection;
import a1.net.NetGame;
import a1.net.NetLogin;
import a1.obj.ObjectVisual;
import a1.utils.*;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.openal.AL;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.newdawn.slick.Color;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;

import static org.lwjgl.opengl.GL11.*;

public class Main {
    private int fps_counter;
    private long last_fps_tick, last_tick;
    private int debug_row_pos;
    public static long DataRecieved;
    public static long DataSended;
    public static Main instance;

    //    , ?
    static public long dt;
    static public int FPS = 0;
    static public int GameState = 0; // 0 - login, 1 - game
    static public Connection LoginConnect = null;
    static public Connection GameConnect = null;

    static public Skin skin;
    public Input input;
    private boolean active = true;

    public static void main(String[] args) throws LWJGLException {
        ErrorHandler.initialize();
        RotateLog();
        Log.init();
        Log.info("build: " + Game.buildVersion());
        Log.info("lwjgl: " + Sys.getVersion());
        Log.info("is 64 bit: " + (Sys.is64Bit() ? "true" : "false"));
        Log.info("Start a1 client...");
        Config.PrintHelpCommads();

        instance = new Main();
        //    
        Config.load_options();
        //  
        Lang.LoadTranslate();
        // ? ?     ?
        if (Config.DebugEngine)
            System.setProperty("org.lwjgl.util.Debug", "true");
        // ?  ?
        Config.ParseCMD(args);
        //   ? ? ?
        Resource.load_versions();
        // ? ??    
        if (Config.update_mode) {
            // ? ??   ?
            if (Resource.srv_versions.get("client") != Config.CLIENT_VERSION) {
                Log.info("my ver=" + Config.CLIENT_VERSION + " new ver=" + Resource.srv_versions.get("client"));
                // ???
                Resource.update_client();
            } else
                // ?  ? 
                Log.info("client is current version. dont need updatig.");
            System.exit(0);
        } else {
            // ?   
            if (instance.initialize()) {
                instance.execute();
                instance.destroy();
            }
            Config.save_options();
            AL.destroy();
            System.exit(0);
        }
    }

    public boolean initialize() {

        GameState = 0;

        Keyboard.enableRepeatEvents(true);
        input = new Input(GUI.getInstance());
        Dialog.Init();

        if (!initDisplay())
            return false;

        last_fps_tick = last_tick = System.currentTimeMillis();
        fps_counter = 0;
        FPS = 0;

        Render2D.LoadSystemFont();
        SetIcon();

        Log.info("adapter: " + Display.getAdapter());
        Log.info("version: " + Display.getVersion());

        Log.info("gl vendor: " + GL11.glGetString(GL11.GL_VENDOR));
        if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object)
            Log.info("gl: GL_ARB_vertex_buffer_object supported!");
        else
            Log.info("gl: GL_ARB_vertex_buffer_object NOT supported!");

        initGL();
        setView(Config.getScreenWidth(), Config.getScreenHeight());

        ResSources.Init();
        skin = new Skin_MyGUI();
        skin.Init();

        return true;
    }

    private void initGL() {
        // enable textures since we're going to use these for our sprites
        GL11.glPointSize(1);
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glDisable(GL11.GL_LIGHTING);

        glClearColor(0.0f, 0.0f, 0.0f, 0);
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

        // disable the OpenGL depth test since we're rendering 2D graphics
        GL11.glDisable(GL11.GL_DEPTH_TEST);
    }

    private boolean initDisplay() {
        try {
            //     ?
            Config.display_modes = Display.getAvailableDisplayModes();

            if (Config.isFullscreen) {
                Display.setDisplayMode(Display.getDesktopDisplayMode());
                Display.setFullscreen(true);
            } else {
                Display.setDisplayMode(new DisplayMode(Config.WindowWidth, Config.WindowHeight));
            }

            // ?   ?
            Display.setLocation(Config.WindowPosX, Config.WindowPosY);
            //  
            //     dlg_Version -     
            // ?
            Display.setTitle("Codename: Origin ver: 0." + Integer.toString(Config.CLIENT_VERSION) + " (prealpha)");

            Display.setVSyncEnabled(Config.VSync);
            Display.setResizable(true);
            Display.setInitialBackground(0, 0, 0);
            Display.create();

            return true;
        } catch (LWJGLException e) {
            Log.info(e.getMessage());
        }
        return false;
    }

    private void setView(int screenWidth, int screenHeight) {
        GL11.glViewport(0, 0, screenWidth, screenHeight);

        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0, screenWidth, screenHeight, 0, -1, 1);

        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
    }

    public void destroy() {
        //  ?  
        GUI.getInstance().root.Unlink();
        //  ? - ? ?  ?
        Display.destroy();
    }

    private void execute() {
        Dialog.Show("dlg_loading");
        dlg_Loading.FillLoading();

        // wait for user to close window
        while (active) {

            if (Display.isActive()) {
                // The window is in the foreground, so we should play the game
                input.Update();
                update();
                render();

                DisplaySync();
            } else {

                update();
                if (Display.isVisible() || Display.isDirty()) {
                    // Only bother rendering if the window is visible or dirty
                    render();
                }

                if (Config.ReduceInBackground) {
                    Display.sync(10);
                } else {
                    DisplaySync();
                }
            }

            if (Display.wasResized())
                WindowResized();

            if (Display.getX() != Config.WindowPosX || Display.getY() != Config.WindowPosY) {
                Config.WindowPosX = Display.getX();
                Config.WindowPosY = Display.getY();
                Config.save_options();
            }

            if (Display.isCloseRequested()) {
                active = !WindowClose();
                break;
            }

            Display.update();
        }
    }

    private boolean WindowClose() {

        Config.save_options();

        return true;
    }

    private void DisplaySync() {
        if (Config.FrameFate > 0 && Config.FrameFate < 10000)
            Display.sync(Config.FrameFate);
    }

    private void update() {
        dt = (System.currentTimeMillis() - last_tick);
        last_tick = System.currentTimeMillis();

        if (GameState == 1) {
            if (GameConnect != null)
                if (!GameConnect.Alive()) {
                    Config.quick_login_mode = false;
                    NetLogin.error_text = Connection.GetErrorReason(GameConnect.network_error);
                    GameState = 0;
                    Dialog.HideAll();
                    dlg_Login.ShowLogin();
                    GameConnect.Close();
                    GameConnect = null;
                    ReleaseAll();
                }
        } else {
            if (LoginConnect != null)
                if (!LoginConnect.Alive()) {
                    Config.quick_login_mode = false;
                    NetLogin.error_text = Connection.GetErrorReason(LoginConnect.network_error);
                    GameState = 0;
                    Dialog.HideAll();
                    dlg_Login.ShowLogin();
                    LoginConnect.Close();
                    LoginConnect = null;
                    ReleaseAll();
                }
        }

        TilesDebug.Update();

        // ?  ??
        Resource.update_load();
        //   
        NetLogin.ProcessPackets();
        //   
        NetGame.ProcessPackets();

        ObjCache.update();
        Dialog.Update();
        dlg_SysMsg.Update();
        Hotbar.UpdateAll();
        GUI.getInstance().Update();
        if (GUI_Debug.active)
            GUI_Debug.Update();

        // handle ALT+ENTER
        if (Input.KeyHit(Keyboard.KEY_RETURN) && Input.isAltPressed() && Config.fullscreen_alt_enter)
            SwitchFullscreenMode();

        Hotkeys.ProcessKey();
    }

    private void SwitchFullscreenMode() {
        try {
            Config.isFullscreen = !Config.isFullscreen;
            if (Config.isFullscreen) {
                // ?  
                Config.WindowWidth = Display.getWidth();
                Config.WindowHeight = Display.getHeight();

                // ? 
                Display.setDisplayMode(Display.getDesktopDisplayMode());
                Config.ScreenWidth = Display.getWidth();
                Config.ScreenHeight = Display.getHeight();

                // " ?!"
                Display.setFullscreen(true);

                // ?
                WindowResized();
            } else {
                //   ?
                Display.setFullscreen(false);

                // ??  
                Display.setDisplayMode(new DisplayMode(Config.WindowWidth, Config.WindowHeight));

                // ?
                WindowResized();
            }

        } catch (LWJGLException e) {
            e.printStackTrace();
        }

    }

    private void render() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        GL11.glLoadIdentity();

        GL11.glPushMatrix();
        GUI.getInstance().Render();
        GL11.glPopMatrix();

        // render debug info
        if (Config.debug)
            DrawDebug();

        fps_counter++;
        if (System.currentTimeMillis() - last_fps_tick > 1000) {
            last_fps_tick = System.currentTimeMillis();
            FPS = fps_counter;
            fps_counter = 0;
        }

    }

    private void DrawDebug() {
        debug_row_pos = 10;
        RenderDebugRow("FPS: " + Integer.toString(FPS));
        RenderDebugRow("Data recv: " + Utils.data2string(DataRecieved));
        RenderDebugRow("Data sent: " + Utils.data2string(DataSended));
        // RenderDebugRow("Memory: "+getMemoryString());
        if (GUI.map != null) {
            RenderDebugRow("map coord: " + Integer.toString(GUI.map.mc.x) + ", " + Integer.toString(GUI.map.mc.y));
            RenderDebugRow("rendered objects=" + GUI.map.render_parts.size());
            RenderDebugRow("tiles rendered: " + Integer.toString(GUI.map.RenderedTiles));
            RenderDebugRow("parts rendered: " + Integer.toString(GUI.map.RenderedObjects));
        }
        RenderDebugRow("Ping=" + NetGame.Ping);
        RenderDebugRow("Mouse: " + Integer.toString(Input.MouseX) + ", " + Integer.toString(Input.MouseY));
        String s = "";
        for (int i = 0; i < 255; i++) {
            if (Keyboard.isKeyDown(i))
                s += " " + Integer.toString(i);
        }
        RenderDebugRow("Keys: " + s);
        RenderDebugRow("Last keyboard: " + Input.debug_str);

        if (GUI.getInstance().mouse_in_control != null)
            RenderDebugRow("mouse in control: " + GUI.getInstance().mouse_in_control.toString());
        else
            RenderDebugRow("<< NULL >> ");

        if (GameState == 1) {
            if (GameConnect != null)
                if (GameConnect.Alive())
                    RenderDebugRow(GameConnect.GetStateDesc());
                else
                    RenderDebugRow(Connection.GetErrorReason(GameConnect.network_error));
            else
                RenderDebugRow("disconnected");
        } else if (NetLogin.error_text.length() > 0)
            RenderDebugRow(NetLogin.error_text);
        else if (LoginConnect != null)
            if (LoginConnect.Alive())
                RenderDebugRow(LoginConnect.GetStateDesc());
            else
                RenderDebugRow(Connection.GetErrorReason(LoginConnect.network_error));
        else
            RenderDebugRow("disconnected");

        if (GUI_Debug.active)
            GUI_Debug.Render();
    }

    private void RenderDebugRow(String text) {
        Render2D.Text("system", 10, debug_row_pos, text, Color.green);
        debug_row_pos += 15;
    }

    // ?    
    private void WindowResized() {
        if (Config.isFullscreen) {
            Config.ScreenHeight_to_save = Config.ScreenHeight;
            Config.ScreenWidth_to_save = Config.ScreenWidth;
        } else {
            Config.WindowWidth = Display.getWidth();
            Config.WindowHeight = Display.getHeight();
        }
        Config.save_options();

        setView(Display.getWidth(), Display.getHeight());

        GUI.getInstance().ResolutionChanged();
        Dialog.ResolutionChanged();
    }

    // ?  (?  ?   ? )
    public static void StartMusic() {
        if (Dialog.IsActive("dlg_game"))
            Sound.PlayMusic("theme1");
        else
            Sound.PlayMusic("menu");
    }

    // ? ?? .     ? 
    public static void ResLoaded() {
        Render2D.InitFonts();

        Config.Apply();
        // ?    - ??   
        if (Config.dev_tile_mode)
            TilesDebug.ParseTilesXML();
        else
            TilesDebug.ParseTilesXML(null);

        Cursor.setCursor("");
        skin.ParseIcons();
    }

    // ?  ?
    private static void SetIcon() {
        ByteBuffer[] bb = new ByteBuffer[3];
        try {
            bb[0] = IconLoader.LoadIconFromPNG(Main.class.getResourceAsStream("/etc/a1_16.png"));
            bb[1] = IconLoader.LoadIconFromPNG(Main.class.getResourceAsStream("/etc/a1_32.png"));
            bb[2] = IconLoader.LoadIconFromPNG(Main.class.getResourceAsStream("/etc/a1_128.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        Display.setIcon(bb);
    }

    //      
    public static void RotateLog() {
        int maxLogs = 2;

        File last = new File("client-" + maxLogs + ".log");
        if (last.exists()) {
            if (!last.delete()) {
                System.err.println("Error removing old log file:" + last);
            }
        }
        for (int i = maxLogs - 1; i > 0; i--) {
            File current = new File("client-" + i + ".log");
            if (current.exists()) {
                if (!current.renameTo(last))
                    System.err.println("Error renaming:" + current + " to:" + last);
            }
            last = current;
        }

        File current = new File("client.log");
        if (current.exists()) {
            if (!current.renameTo(last))
                System.err.println("Error renaming:" + current + " to:" + last);
        }
    }

    public static String getMemoryString() {
        Runtime rt = Runtime.getRuntime();
        long free = rt.freeMemory();
        long total = rt.totalMemory();
        long max = rt.maxMemory();

        long used = total - free;

        long percent1 = used * 100L / total;
        long percent2 = used * 100L / max;

        return "Working memory: " + percent1 + "% (" + used + "/" + total + ")" + "  VM Max: " + percent2 + "% ("
                + used + "/" + max + ")";
    }

    static public void GlobalError(String msg) {
        Log.info(msg);
        System.exit(-1);
    }

    // ? ? ? ??  ?
    static public void ReleaseAll() {
        ObjCache.ClearAll();
        FlyText.Clear();
        MapCache.grids.clear();
        Player.Clear();

        Config.save_options();
        Dialog.HideAll();
        ObjectVisual.CloseAll();
        Hotbar.ClearAll();
        Cursor.setCursor("");

        if (GameConnect != null)
            GameConnect.Close();
        GameConnect = null;

        if (LoginConnect != null)
            LoginConnect.Close();
        LoginConnect = null;

        NetLogin.LastPingTime = 0;
        NetLogin.login_state = "";

        dlg_Login.ShowLogin();
    }
}