private synchronized void initLevel() {
   if (level == null) return;
   // level.init();
   players[0] =
       new Player(
           synchedKeys[0],
           synchedMouseButtons[0],
           level.width * Tile.WIDTH / 2 - 16,
           (level.height - 5 - 1) * Tile.HEIGHT - 16,
           Team.Team1,
           localTeam);
   players[0].setFacing(4);
   level.addEntity(players[0]);
   level.addEntity(new Base(34 * Tile.WIDTH, 7 * Tile.WIDTH, Team.Team1, localTeam));
   if (isMultiplayer) {
     players[1] =
         new Player(
             synchedKeys[1],
             synchedMouseButtons[1],
             level.width * Tile.WIDTH / 2 - 16,
             7 * Tile.HEIGHT - 16,
             Team.Team2,
             localTeam);
     players[1].setLocalTeam(localTeam);
     level.addEntity(players[1]);
     level.addEntity(new Base(32 * Tile.WIDTH - 20, 32 * Tile.WIDTH - 20, Team.Team2, localTeam));
   }
   player = players[localId];
   player.setCanSee(true);
 }
 private synchronized void createLevel(LevelInformation li) {
   try {
     level = Level.fromFile(li);
   } catch (Exception ex) {
     ex.printStackTrace();
     showError("Unable to load map.");
     return;
   }
   initLevel();
   paused = false;
 }
  private synchronized void createLevel(String levelFile) {
    try {
      level = Level.fromFile(levelFile);
    } catch (Exception ex) {
      throw new RuntimeException("Unable to load level", ex);
    }

    level.init();

    players[0] =
        new Player(
            synchedKeys[0],
            mouseButtons,
            level.width * Tile.WIDTH / 2 - 16,
            (level.height - 5 - 1) * Tile.HEIGHT - 16,
            Team.Team1);
    players[0].setFacing(4);
    level.addEntity(players[0]);
    level.addEntity(new Base(34 * Tile.WIDTH, 7 * Tile.WIDTH, Team.Team1));
    if (isMultiplayer) {
      players[1] =
          new Player(
              synchedKeys[1],
              mouseButtons,
              level.width * Tile.WIDTH / 2 - 16,
              7 * Tile.HEIGHT - 16,
              Team.Team2);
      // players[1] = new Player(synchedKeys[1], 10, 10);
      level.addEntity(players[1]);
      level.addEntity(new Base(32 * Tile.WIDTH - 20, 32 * Tile.WIDTH - 20, Team.Team2));
    }
    player = players[localId];
    player.setCanSee(true);
  }
  private synchronized void render(Graphics g) {
    if (level != null) {
      int xScroll = (int) (player.pos.x - screen.w / 2);
      int yScroll = (int) (player.pos.y - (screen.h - 24) / 2);
      soundPlayer.setListenerPosition((float) player.pos.x, (float) player.pos.y);
      level.render(screen, xScroll, yScroll);
    }
    if (!menuStack.isEmpty()) {
      menuStack.peek().render(screen);
    }

    if (Options.getAsBoolean(Options.DRAW_FPS, Options.VALUE_FALSE)) {
      Font.draw(screen, texts.FPS(fps), 10, 10);
    }

    if (player != null && menuStack.size() == 0) {
      if (isMultiplayer) {
        Font.draw(screen, texts.latency(latencyCacheReady() ? "" + avgLatency() : "-"), 10, 20);
      }

      Font.draw(screen, texts.health(player.health, player.maxHealth), 340, screen.h - 16);
      Font.draw(screen, texts.money(player.score), 340, screen.h - 27);
      Font.draw(screen, texts.nextLevel((int) player.getNextLevel()), 340, screen.h - 38);
      Font.draw(screen, texts.playerExp((int) player.pexp), 340, screen.h - 49);
      Font.draw(screen, texts.playerLevel(player.plevel), 340, screen.h - 60);
    }

    if (isMultiplayer && menuStack.isEmpty()) {
      chat.render(screen);
    }

    g.setColor(Color.BLACK);

    g.fillRect(0, 0, getWidth(), getHeight());
    g.translate((getWidth() - GAME_WIDTH * SCALE) / 2, (getHeight() - GAME_HEIGHT * SCALE) / 2);
    g.clipRect(0, 0, GAME_WIDTH * SCALE, GAME_HEIGHT * SCALE);

    if (!menuStack.isEmpty() || level != null) {

      // render mouse
      renderMouse(screen, mouseButtons);

      g.drawImage(screen.image, 0, 0, GAME_WIDTH * SCALE, GAME_HEIGHT * SCALE, null);
    }
  }
  private synchronized void render(Graphics g) {
    if (level != null) {
      int xScroll = (int) (player.pos.x - screen.w / 2);
      int yScroll = (int) (player.pos.y - (screen.h - 24) / 2);
      soundPlayer.setListenerPosition((float) player.pos.x, (float) player.pos.y);
      level.render(screen, xScroll, yScroll);
    }
    if (!menuStack.isEmpty()) {
      menuStack.peek().render(screen);
    }

    Font.draw(screen, "FPS: " + fps, 10, 10);
    // for (int p = 0; p < players.length; p++) {
    // if (players[p] != null) {
    // String msg = "P" + (p + 1) + ": " + players[p].getScore();
    // Font.draw(screen, msg, 320, screen.h - 24 + p * 8);
    // }
    // }
    if (player != null && menuStack.size() == 0) {
      Font.draw(screen, player.health + " / 10", 340, screen.h - 19);
      Font.draw(screen, "" + player.score, 340, screen.h - 33);
    }

    g.setColor(Color.BLACK);

    g.fillRect(0, 0, getWidth(), getHeight());
    g.translate((getWidth() - GAME_WIDTH * SCALE) / 2, (getHeight() - GAME_HEIGHT * SCALE) / 2);
    g.clipRect(0, 0, GAME_WIDTH * SCALE, GAME_HEIGHT * SCALE);

    if (!menuStack.isEmpty() || level != null) {

      // render mouse
      renderMouse(screen, mouseButtons);

      g.drawImage(screen.image, 0, 0, GAME_WIDTH * SCALE, GAME_HEIGHT * SCALE, null);
    }

    // String msg = "FPS: " + fps;
    // g.setColor(Color.LIGHT_GRAY);
    // g.drawString(msg, 11, 11);
    // g.setColor(Color.WHITE);
    // g.drawString(msg, 10, 10);

  }
  private synchronized void render(Graphics g) {
    if (level != null) {
      int xScroll = (int) (player.pos.x - screen.w / 2);
      int yScroll = (int) (player.pos.y - (screen.h - 24) / 2);
      soundPlayer.setListenerPosition((float) player.pos.x, (float) player.pos.y);
      level.render(screen, xScroll, yScroll);
    }
    if (!menuStack.isEmpty()) {
      menuStack.peek().render(screen);
    }

    boolean drawFPS = Options.get("drawFPS") != null && Options.get("drawFPS").equals("true");
    if (drawFPS) {
      Font.draw(screen, texts.FPS(fps), 10, 10);
    }

    if (player != null && menuStack.size() == 0) {
      Font.draw(screen, texts.health(player.health, player.maxHealth), 340, screen.h - 16);
      Font.draw(screen, texts.money(player.score), 340, screen.h - 27);
      Font.draw(screen, texts.nextLevel((int) player.getNextLevel()), 340, screen.h - 38);
      Font.draw(screen, texts.playerExp((int) player.pexp), 340, screen.h - 49);
      Font.draw(screen, texts.playerLevel(player.plevel), 340, screen.h - 60);
    }

    g.setColor(Color.BLACK);

    g.fillRect(0, 0, getWidth(), getHeight());
    g.translate((getWidth() - GAME_WIDTH * SCALE) / 2, (getHeight() - GAME_HEIGHT * SCALE) / 2);
    g.clipRect(0, 0, GAME_WIDTH * SCALE, GAME_HEIGHT * SCALE);

    if (!menuStack.isEmpty() || level != null) {

      // render mouse
      renderMouse(screen, mouseButtons);

      g.drawImage(screen.image, 0, 0, GAME_WIDTH * SCALE, GAME_HEIGHT * SCALE, null);
    }
  }
  private void tick() {
    // Not-In-Focus-Pause
    if (this.isFocusOwner() && level != null) {
      paused2 = false;
    }

    if (!this.isFocusOwner() && level != null) {
      keys.release();
      mouseButtons.releaseAll();
      if (!paused && !paused2) {
        PauseCommand pauseCommand = new PauseCommand(true);
        synchronizer.addCommand(pauseCommand);
        paused2 = true;
      }
    }
    if (isMultiplayer) {
      tickChat();
    }

    if (requestToggleFullscreen || keys.fullscreen.wasPressed()) {
      requestToggleFullscreen = false;
      setFullscreen(!fullscreen);
    }

    if (level != null && level.victoryConditions != null) {
      if (level.victoryConditions.isVictoryConditionAchieved()) {
        addMenu(new WinMenu(GAME_WIDTH, GAME_HEIGHT, level.victoryConditions.playerVictorious()));
        level = null;
        return;
      }
    }

    if (packetLink != null) {
      packetLink.tick();
    }

    mouseButtons.setPosition(getMousePosition());
    if (!menuStack.isEmpty()) {
      menuStack.peek().tick(mouseButtons);
    }
    if (mouseMoved) {
      mouseMoved = false;
      mouseHideTime = 0;
      if (mouseButtons.mouseHidden) {
        mouseButtons.mouseHidden = false;
      }
    }
    if (mouseHideTime < 60) {
      mouseHideTime++;
      if (mouseHideTime == 60) {
        mouseButtons.mouseHidden = true;
      }
    }

    if (level == null) {
      mouseButtons.tick();
    } else if (level != null) {
      if (synchronizer.preTurn()) {
        synchronizer.postTurn();

        for (int index = 0; index < mouseButtons.currentState.length; index++) {
          boolean nextState = mouseButtons.nextState[index];
          if (mouseButtons.isDown(index) != nextState) {
            synchronizer.addCommand(new ChangeMouseButtonCommand(index, nextState));
          }
        }

        synchronizer.addCommand(
            new ChangeMouseCoordinateCommand(
                mouseButtons.getX(), mouseButtons.getY(), mouseButtons.mouseHidden));

        mouseButtons.tick();
        for (MouseButtons sMouseButtons : synchedMouseButtons) {
          sMouseButtons.tick();
        }

        if (!paused) {
          for (int index = 0; index < keys.getAll().size(); index++) {
            Keys.Key key = keys.getAll().get(index);
            boolean nextState = key.nextState;
            if (key.isDown != nextState) {
              synchronizer.addCommand(new ChangeKeyCommand(index, nextState));
            }
          }

          keys.tick();
          for (Keys skeys : synchedKeys) {
            skeys.tick();
          }

          if (keys.pause.wasPressed()) {
            keys.release();
            mouseButtons.releaseAll();
            synchronizer.addCommand(new PauseCommand(true));
          }

          level.tick();
        }

        // every 4 minutes, start new background music :)
        if (System.currentTimeMillis() / 1000 > nextMusicInterval) {
          nextMusicInterval = (System.currentTimeMillis() / 1000) + 4 * 60;
          soundPlayer.startBackgroundMusic();
        }

        if (keys.screenShot.isDown) {
          takeScreenShot();
        }
      }
    }

    if (createServerState == 1) {
      createServerState = 2;

      synchronizer = new TurnSynchronizer(MojamComponent.this, packetLink, localId, 2);

      clearMenus();
      createLevel(TitleMenu.level, TitleMenu.defaultGameMode);

      synchronizer.setStarted(true);
      if (TitleMenu.level.vanilla) {
        packetLink.sendPacket(
            new StartGamePacket(
                TurnSynchronizer.synchedSeed,
                TitleMenu.level.getUniversalPath(),
                DifficultyList.getDifficultyID(TitleMenu.difficulty)));
      } else {
        packetLink.sendPacket(
            new StartGamePacketCustom(
                TurnSynchronizer.synchedSeed,
                level,
                DifficultyList.getDifficultyID(TitleMenu.difficulty)));
      }
      packetLink.setPacketListener(MojamComponent.this);
    }
  }
  private void tick() {

    if (packetLink != null) {
      packetLink.tick();
    }

    mouseButtons.setPosition(getMousePosition());
    if (!menuStack.isEmpty()) {
      menuStack.peek().tick(mouseButtons);
    }
    if (mouseMoved) {
      mouseMoved = false;
      mouseHideTime = 0;
      if (mouseHidden) {
        mouseHidden = false;
      }
    }
    if (mouseHideTime < 60) {
      mouseHideTime++;
      if (mouseHideTime == 60) {
        mouseHidden = true;
      }
    }
    mouseButtons.tick();

    if (level != null) {
      if (synchronizer.preTurn()) {
        synchronizer.postTurn();

        if (!paused) {
          for (int index = 0; index < keys.getAll().size(); index++) {
            Keys.Key key = keys.getAll().get(index);
            boolean nextState = key.nextState;
            if (key.isDown != nextState) {
              synchronizer.addCommand(new ChangeKeyCommand(index, nextState));
            }
          }

          keys.tick();
          for (Keys skeys : synchedKeys) {
            skeys.tick();
          }

          if (keys.pause.wasPressed()) {
            keys.release();
            synchronizer.addCommand(new PauseCommand(true));
          }

          if (keys.fullscreen.wasPressed()) {
            setFullscreen(!fullscreen);
          }

          // if mouse is in use, update player orientation before level tick
          if (!mouseHidden) {

            // update player mouse, in world pixels relative to
            // player
            player.setAimByMouse(
                ((mouseButtons.getX() / SCALE) - (screen.w / 2)),
                (((mouseButtons.getY() / SCALE) + 24) - (screen.h / 2)));
          } else {
            player.setAimByKeyboard();
          }

          level.tick();
        }

        // every 4 minutes, start new background music :)
        if (System.currentTimeMillis() / 1000 > nextMusicInterval) {
          nextMusicInterval = (System.currentTimeMillis() / 1000) + 4 * 60;
          soundPlayer.startBackgroundMusic();
        }

        if (keys.screenShot.isDown) {
          takeScreenShot();
        }
      }
    }

    if (createServerState == 1) {
      createServerState = 2;

      synchronizer = new TurnSynchronizer(MojamComponent.this, packetLink, localId, 2);

      clearMenus();
      createLevel(TitleMenu.level);

      synchronizer.setStarted(true);
      if (TitleMenu.level.vanilla) {
        packetLink.sendPacket(
            new StartGamePacket(
                TurnSynchronizer.synchedSeed,
                TitleMenu.level.getUniversalPath(),
                DifficultyList.getDifficultyID(TitleMenu.difficulty)));
      } else {
        packetLink.sendPacket(
            new StartGamePacketCustom(
                TurnSynchronizer.synchedSeed,
                level,
                DifficultyList.getDifficultyID(TitleMenu.difficulty)));
      }
      packetLink.setPacketListener(MojamComponent.this);
    }
  }
  private void tick() {
    if (level != null) {
      if (level.player1Score >= Level.TARGET_SCORE) {
        addMenu(new WinMenu(GAME_WIDTH, GAME_HEIGHT, 1));
        level = null;
        return;
      }
      if (level.player2Score >= Level.TARGET_SCORE) {
        addMenu(new WinMenu(GAME_WIDTH, GAME_HEIGHT, 2));
        level = null;
        return;
      }
      if (keys.escape.wasPressed()) {
        clearMenus();
        addMenu(new TitleMenu(GAME_WIDTH, GAME_HEIGHT));
        level = null;
        return;
      }
    }
    if (packetLink != null) {
      packetLink.tick();
    }

    mouseButtons.setPosition(getMousePosition());
    if (!menuStack.isEmpty()) {
      menuStack.peek().tick(mouseButtons);
    }
    if (mouseMoved) {
      mouseMoved = false;
      mouseHideTime = 0;
      if (mouseHidden) {
        mouseHidden = false;
      }
    }
    if (mouseHideTime < 60) {
      mouseHideTime++;
      if (mouseHideTime == 60) {
        mouseHidden = true;
      }
    }
    mouseButtons.tick();

    if (level != null) {
      if (synchronizer.preTurn()) {
        synchronizer.postTurn();
        for (int index = 0; index < keys.getAll().size(); index++) {
          Keys.Key key = keys.getAll().get(index);
          boolean nextState = key.nextState;
          if (key.isDown != nextState) {
            synchronizer.addCommand(new ChangeKeyCommand(index, nextState));
          }
        }
        if (keys.save.isDown) {
          level.save();
        }
        keys.tick();
        for (Keys skeys : synchedKeys) {
          skeys.tick();
        }

        // if mouse is in use, update player orientation before level
        // tick
        if (!mouseHidden) {

          // update player mouse, in world pixels relative to player
          player.setAimByMouse(
              ((mouseButtons.getX() / SCALE) - (screen.w / 2)),
              (((mouseButtons.getY() / SCALE) + 24) - (screen.h / 2)));
        } else {
          player.setAimByKeyboard();
        }

        level.tick();
      }
    }

    if (createServerState == 1) {
      createServerState = 2;

      synchronizer = new TurnSynchronizer(MojamComponent.this, packetLink, localId, 2);

      clearMenus();
      createLevel(TitleMenu.level);

      synchronizer.setStarted(true);
      packetLink.sendPacket(new StartGamePacket(TurnSynchronizer.synchedSeed, TitleMenu.level));
      packetLink.setPacketListener(MojamComponent.this);
    }
  }