@SuppressWarnings({"rawtypes", "unchecked"})
  @Override
  public void saveClan(Clan clan) {
    Pool<SQLSession> pool = Static.currentLink().getSQLPool();

    SQLSession sql = null;
    try {
      sql = pool.acquire();

      Statement st = sql.createStatement();
      ResultSet rs =
          st.executeQuery("SELECT * FROM clans WHERE owner='" + clan.getOwner() + "' LIMIT 1");
      if (!rs.next()) {
        st.executeUpdate("INSERT INTO clans (owner) VALUES ('" + clan.getOwner() + "')");
      }
      rs.close();

      StringBuilder query = new StringBuilder();
      query.append("UPDATE clans SET");
      query.append(" name='").append(clan.getName()).append("'");
      query.append(", enabled='").append(clan.isEnabled() ? 1 : 0).append("'");
      query.append(", enterReq='").append(clan.getEnterRequirement().intValue()).append("'");
      query.append(", talkReq='").append(clan.getTalkRequirement().intValue()).append("'");
      query.append(", kickReq='").append(clan.getKickRequirement().intValue()).append("'");
      query
          .append(", lootShareReq='")
          .append(clan.getLootShareRequirement().intValue())
          .append("'");

      List[] ranks = new List[9];
      for (Map.Entry<String, Rank> ranked : clan.getRanks().entrySet()) {
        List rankList = ranks[ranked.getValue().intValue() + 1];
        if (rankList == null) {
          rankList = ranks[ranked.getValue().intValue() + 1] = new ArrayList();
        }

        rankList.add(ranked.getKey());
      }
      List curList;

      query
          .append(", recruits='")
          .append(
              (curList = ranks[Rank.RECRUIT.intValue() + 1]) != null
                  ? ArrayUtilities.toString(curList.toArray(new String[0]))
                  : "")
          .append("'");
      query
          .append(", corporals='")
          .append(
              (curList = ranks[Rank.CORPORAL.intValue() + 1]) != null
                  ? ArrayUtilities.toString(curList.toArray(new String[0]))
                  : "")
          .append("'");
      query
          .append(", sergeants='")
          .append(
              (curList = ranks[Rank.SERGEANT.intValue() + 1]) != null
                  ? ArrayUtilities.toString(curList.toArray(new String[0]))
                  : "")
          .append("'");
      query
          .append(", lieutenants='")
          .append(
              (curList = ranks[Rank.LIEUTENANT.intValue() + 1]) != null
                  ? ArrayUtilities.toString(curList.toArray(new String[0]))
                  : "")
          .append("'");
      query
          .append(", captains='")
          .append(
              (curList = ranks[Rank.CAPTAIN.intValue() + 1]) != null
                  ? ArrayUtilities.toString(curList.toArray(new String[0]))
                  : "")
          .append("'");
      query
          .append(", generals='")
          .append(
              (curList = ranks[Rank.GENERAL.intValue() + 1]) != null
                  ? ArrayUtilities.toString(curList.toArray(new String[0]))
                  : "")
          .append("'");

      query.append(" WHERE owner='").append(clan.getOwner()).append("'");
      st.executeUpdate(query.toString());
      st.close();
    } catch (SQLException e) {
      logger.error("Error saving clan [owner=" + clan + "]", e);
    } finally {
      if (sql != null) {
        pool.release(sql);
      }
    }
  }
  @Override
  public void savePlayer(String userName, boolean lobby, PlayerSave player) {
    Pool<SQLSession> pool = Static.currentLink().getSQLPool();

    SQLSession sql = null;
    try {
      sql = pool.acquire();

      StringBuilder query = new StringBuilder();
      query.append("UPDATE playersave SET");
      query.append(" lastIPs='").append(ArrayUtilities.toString(player.lastIPs)).append("'");
      query.append(", muted='").append(player.isMuted ? 1 : 0).append("'");
      query.append(", lastLoggedIn='").append(System.currentTimeMillis()).append("'");
      query.append(", friends='").append(ArrayUtilities.toString(player.friends)).append("'");
      query.append(", ignores='").append(ArrayUtilities.toString(player.ignores)).append("'");
      query.append(", pmSetting='").append(player.privateChatSetting).append("'");
      query.append(", pmColor='").append(player.privateChatColor).append("'");
      if (!lobby) {
        query.append(", x='").append(player.x).append("'");
        query.append(", y='").append(player.y).append("'");
        query.append(", z='").append(player.z).append("'");
        query.append(", runToggled='").append(player.runToggled ? 1 : 0).append("'");
        query.append(", runEnergy='").append(player.runEnergy).append("'");
        query.append(", inv='").append(ArrayUtilities.toString(player.inv)).append("'");
        query.append(", invN='").append(ArrayUtilities.toString(player.invN)).append("'");
        query.append(", equip='").append(ArrayUtilities.toString(player.equip)).append("'");
        query.append(", equipN='").append(ArrayUtilities.toString(player.equipN)).append("'");

        int[] bank = new int[player.bank.length];
        for (int i = 0; i < bank.length; i++) {
          bank[i] = player.bank[i][0];
        }
        query.append(", bank='").append(ArrayUtilities.toString(bank)).append("'");
        for (int i = 0; i < bank.length; i++) {
          bank[i] = player.bank[i][1];
        }
        query.append(", bankN='").append(ArrayUtilities.toString(bank)).append("'");
        for (int i = 0; i < bank.length; i++) {
          bank[i] = player.bank[i][2];
        }
        query.append(", bankT='").append(ArrayUtilities.toString(bank)).append("'");

        query.append(", level='").append(ArrayUtilities.toString(player.level)).append("'");
        query.append(", exp='").append(ArrayUtilities.toString(player.exp)).append("'");
        query.append(", xpCounter='").append(player.xpCounter).append("'");
        query.append(", autoRetaliate='").append(player.autoRetaliate ? 1 : 0).append("'");
        query.append(", attackStyle='").append(player.attackStyle).append("'");
        query.append(", prayerBook='").append(player.prayerBook ? 1 : 0).append("'");
        query
            .append(", quickPrayers='")
            .append(ArrayUtilities.toString(player.quickPrayers))
            .append("'");
        query.append(", spellBook='").append(player.spellBook).append("'");
        query.append(", specialEnergy='").append(player.specialEnergy).append("'");
        query.append(", looks='").append(ArrayUtilities.toString(player.looks)).append("'");
        query.append(", colors='").append(ArrayUtilities.toString(player.colours)).append("'");
        query.append(", muted='").append(player.isMuted ? 1 : 0).append("'");
        query.append(", skulled='").append(player.isSkulled ? 1 : 0).append("'");
        query.append(", skullTimer='").append(player.skullTimer).append("'");
        query.append(", lastClan=");
        if (player.lastClan == null) {
          query.append("NULL");
        } else {
          query.append("'").append(player.lastClan).append("'");
        }
      }
      query.append(" WHERE id='").append(player.userId).append("'");
      Statement st = sql.createStatement();
      st.executeUpdate(query.toString());
      st.close();
    } catch (SQLException e) {
      logger.error("Error saving player [name=" + userName + "]", e);
    } finally {
      if (sql != null) {
        pool.release(sql);
      }
    }
  }