Atrinik Client 2.5
client/upgrader.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00035 static const char *const client_versions[] =
00036 {
00037     "2.0", "2.5"
00038 };
00039 
00047 static void upgrade_20_to_25(const char *from, const char *to)
00048 {
00049     char src[MAX_BUF], buf[HUGE_BUF];
00050     FILE *fp;
00051 
00052     /* interface.gui and scripts_autoload changed locations in 2.5, copy
00053      * them to the correct new location. */
00054     copy_if_exists(from, to, "interface.gui", "settings/interface.gui");
00055     copy_if_exists(from, to, "scripts_autoload", "settings/scripts_autoload");
00056     /* Copy over settings directory - in 2.0 and before only used to have
00057      * ignore lists. */
00058     copy_if_exists(from, to, "settings", "settings");
00059 
00060     /* Try to upgrade keybindings, if they exist. */
00061     snprintf(src, sizeof(src), "%s/keys.dat", from);
00062     fp = fopen(src, "r");
00063 
00064     if (fp)
00065     {
00066         int keycode, repeat;
00067         char keyname[MAX_BUF], command[HUGE_BUF];
00068 
00069         keybind_load();
00070 
00071         /* Read the old keys.dat file. */
00072         while (fgets(buf, sizeof(buf) - 1, fp))
00073         {
00074             /* Try to parse the macro definition lines. */
00075             if (sscanf(buf, "%d %d \"%200[^\"]\" \"%2000[^\"]\"", &keycode, &repeat, keyname, command) == 4)
00076             {
00077                 keybind_struct *keybind;
00078 
00079                 /* Is it a command? */
00080                 if (*command == '/')
00081                 {
00082                     keybind = keybind_find_by_command(command);
00083 
00084                     /* Does not exist yet, add it. */
00085                     if (!keybind)
00086                     {
00087                         keybind = keybind_add(keycode, 0, command);
00088                     }
00089                     else
00090                     {
00091                         keybind->key = keycode;
00092                     }
00093 
00094                     keybind->repeat = repeat;
00095                 }
00096                 else if (*command == '?')
00097                 {
00098                     const char *new_cmd = command;
00099 
00100                     if (!strcmp(command, "?M_NORTH"))
00101                     {
00102                         new_cmd = "?MOVE_N";
00103                     }
00104                     else if (!strcmp(command, "?M_NORTHEAST"))
00105                     {
00106                         new_cmd = "?MOVE_NE";
00107                     }
00108                     else if (!strcmp(command, "?M_EAST"))
00109                     {
00110                         new_cmd = "?MOVE_E";
00111                     }
00112                     else if (!strcmp(command, "?M_SOUTHEAST"))
00113                     {
00114                         new_cmd = "?MOVE_SE";
00115                     }
00116                     else if (!strcmp(command, "?M_SOUTH"))
00117                     {
00118                         new_cmd = "?MOVE_S";
00119                     }
00120                     else if (!strcmp(command, "?M_SOUTHWEST"))
00121                     {
00122                         new_cmd = "?MOVE_SW";
00123                     }
00124                     else if (!strcmp(command, "?M_WEST"))
00125                     {
00126                         new_cmd = "?MOVE_W";
00127                     }
00128                     else if (!strcmp(command, "?M_NORTHWEST"))
00129                     {
00130                         new_cmd = "?MOVE_NW";
00131                     }
00132                     else if (!strcmp(command, "?M_STAY"))
00133                     {
00134                         new_cmd = "?MOVE_STAY";
00135                     }
00136                     else if (!strcmp(command, "?M_UP"))
00137                     {
00138                         new_cmd = "?UP";
00139                     }
00140                     else if (!strcmp(command, "?M_DOWN"))
00141                     {
00142                         new_cmd = "?DOWN";
00143                     }
00144                     else if (!strcmp(command, "?M_LEFT"))
00145                     {
00146                         new_cmd = "?LEFT";
00147                     }
00148                     else if (!strcmp(command, "?M_RIGHT"))
00149                     {
00150                         new_cmd = "?RIGHT";
00151                     }
00152                     else if (!strcmp(command, "?M_SPELL_LIST"))
00153                     {
00154                         new_cmd = "?SPELL_LIST";
00155                     }
00156                     else if (!strcmp(command, "?M_SKILL_LIST"))
00157                     {
00158                         new_cmd = "?SKILL_LIST";
00159                     }
00160                     else if (!strcmp(command, "?M_HELP"))
00161                     {
00162                         new_cmd = "?HELP";
00163                     }
00164                     else if (!strcmp(command, "?M_KEYBIND"))
00165                     {
00166                         new_cmd = "?PARTY_LIST";
00167                     }
00168                     else if (!strcmp(command, "?M_QLIST"))
00169                     {
00170                         new_cmd = "?QLIST";
00171                     }
00172                     else if (!strcmp(command, "?M_RANGE"))
00173                     {
00174                         new_cmd = "?RANGE";
00175                     }
00176                     else if (!strcmp(command, "?M_FIRE_READY"))
00177                     {
00178                         new_cmd = "?FIRE_READY";
00179                     }
00180                     else if (!strcmp(command, "?COMBAT_TOGGLE"))
00181                     {
00182                         new_cmd = "?COMBAT";
00183                     }
00184                     else if (!strcmp(command, "?M_TARGET_ENEMY"))
00185                     {
00186                         new_cmd = "?TARGET_ENEMY";
00187                     }
00188                     else if (!strcmp(command, "?M_TARGET_FRIEND"))
00189                     {
00190                         new_cmd = "?TARGET_FRIEND";
00191                     }
00192                     else
00193                     {
00194                         continue;
00195                     }
00196 
00197                     keybind = keybind_find_by_command(new_cmd);
00198 
00199                     if (keybind)
00200                     {
00201                         keybind->key = keycode;
00202                     }
00203                 }
00204             }
00205         }
00206 
00207         keybind_deinit();
00208         fclose(fp);
00209     }
00210 
00211     /* Try to upgrade options. */
00212     snprintf(src, sizeof(src), "%s/options.dat", from);
00213     fp = fopen(src, "r");
00214 
00215     if (fp)
00216     {
00217         char option_name[MAX_BUF];
00218         int option_value;
00219 
00220         settings_init();
00221 
00222         /* Read the old options.dat file. */
00223         while (fgets(buf, sizeof(buf) - 1, fp))
00224         {
00225             /* Handle the x/y options. */
00226             if (!strncmp(buf, "%3x ", 4))
00227             {
00228                 setting_set_int(OPT_CAT_CLIENT, OPT_RESOLUTION_X, atoi(buf + 4));
00229                 continue;
00230             }
00231             else if (!strncmp(buf, "%3y ", 4))
00232             {
00233                 setting_set_int(OPT_CAT_CLIENT, OPT_RESOLUTION_Y, atoi(buf + 4));
00234                 continue;
00235             }
00236 
00237             /* Parse the option lines. */
00238             if (sscanf(buf, "%200[^:]: %d", option_name, &option_value) == 2)
00239             {
00240                 int cat = -1, setting = -1;
00241 
00242                 if (!strcmp(option_name, "Playerdoll"))
00243                 {
00244                     cat = OPT_CAT_GENERAL;
00245                     setting = OPT_PLAYERDOLL;
00246                 }
00247                 else if (!strcmp(option_name, "Show yourself targeted"))
00248                 {
00249                     cat = OPT_CAT_GENERAL;
00250                     setting = OPT_TARGET_SELF;
00251                 }
00252                 else if (!strcmp(option_name, "Collect mode"))
00253                 {
00254                     cat = OPT_CAT_GENERAL;
00255                     setting = OPT_COLLECT_MODE;
00256                 }
00257                 else if (!strcmp(option_name, "Exp display"))
00258                 {
00259                     cat = OPT_CAT_GENERAL;
00260                     setting = OPT_EXP_DISPLAY;
00261                 }
00262                 else if (!strcmp(option_name, "Chat Timestamps"))
00263                 {
00264                     cat = OPT_CAT_GENERAL;
00265                     setting = OPT_CHAT_TIMESTAMPS;
00266                 }
00267                 else if (!strcmp(option_name, "Maximum chat lines"))
00268                 {
00269                     cat = OPT_CAT_GENERAL;
00270                     setting = OPT_MAX_CHAT_LINES;
00271                 }
00272                 else if (!strcmp(option_name, "Fullscreen"))
00273                 {
00274                     cat = OPT_CAT_CLIENT;
00275                     setting = OPT_FULLSCREEN;
00276                 }
00277                 else if (!strcmp(option_name, "Resolution"))
00278                 {
00279                     cat = OPT_CAT_CLIENT;
00280                     setting = OPT_RESOLUTION;
00281                 }
00282                 else if (!strcmp(option_name, "Player Names"))
00283                 {
00284                     cat = OPT_CAT_MAP;
00285                     setting = OPT_PLAYER_NAMES;
00286                 }
00287                 else if (!strcmp(option_name, "Playfield zoom"))
00288                 {
00289                     cat = OPT_CAT_MAP;
00290                     setting = OPT_MAP_ZOOM;
00291                 }
00292                 else if (!strcmp(option_name, "Low health warning"))
00293                 {
00294                     cat = OPT_CAT_MAP;
00295                     setting = OPT_HEALTH_WARNING;
00296                 }
00297                 else if (!strcmp(option_name, "Low food warning"))
00298                 {
00299                     cat = OPT_CAT_MAP;
00300                     setting = OPT_FOOD_WARNING;
00301                 }
00302                 else if (!strcmp(option_name, "Sound volume"))
00303                 {
00304                     cat = OPT_CAT_SOUND;
00305                     setting = OPT_VOLUME_SOUND;
00306                 }
00307                 else if (!strcmp(option_name, "Music volume"))
00308                 {
00309                     cat = OPT_CAT_SOUND;
00310                     setting = OPT_VOLUME_MUSIC;
00311                 }
00312                 else if (!strcmp(option_name, "Show Framerate"))
00313                 {
00314                     cat = OPT_CAT_DEVEL;
00315                     setting = OPT_SHOW_FPS;
00316                 }
00317                 else if (!strcmp(option_name, "Enable quickport"))
00318                 {
00319                     cat = OPT_CAT_DEVEL;
00320                     setting = OPT_QUICKPORT;
00321                 }
00322 
00323                 if (cat != -1 && setting != -1)
00324                 {
00325                     setting_set_int(cat, setting, option_value);
00326                 }
00327             }
00328         }
00329 
00330         settings_deinit();
00331         fclose(fp);
00332     }
00333 }
00334 
00338 void upgrader_init()
00339 {
00340     char tmp[HUGE_BUF], tmp2[HUGE_BUF], version[MAX_BUF];
00341     size_t i;
00342 
00343     snprintf(tmp, sizeof(tmp), "%s/.atrinik", get_config_dir());
00344 
00345     /* The .atrinik directory doesn't exist yet, nothing to migrate. */
00346     if (access(tmp, R_OK) != 0)
00347     {
00348         return;
00349     }
00350 
00351     snprintf(tmp, sizeof(tmp), "%s/.atrinik/%s", get_config_dir(), package_get_version_partial(version, sizeof(version)));
00352 
00353     /* If the settings directory for the current version already exists,
00354      * leave. */
00355     if (access(tmp, R_OK) == 0)
00356     {
00357         return;
00358     }
00359 
00360     /* Look through the client versions, but skip the last entry, which
00361      * should be the current version.
00362      *
00363      * The logic is that the upgrader will attempt to go through each
00364      * version, and migrate settings into the next version. For example,
00365      * 2.0 -> 2.5, 2.5 -> 3.0, etc. */
00366     for (i = 0; i < arraysize(client_versions) - 1; i++)
00367     {
00368         /* Construct the paths to the version we're looking at in the
00369          * array, and the version after that. */
00370         snprintf(tmp, sizeof(tmp), "%s/.atrinik/%s", get_config_dir(), client_versions[i]);
00371         snprintf(tmp2, sizeof(tmp2), "%s/.atrinik/%s", get_config_dir(), client_versions[i + 1]);
00372 
00373         /* Only migrate if the settings for the version we're looking at
00374          * exist, and the next version directory does not exist. */
00375         if (access(tmp, R_OK) != 0 || access(tmp2, R_OK) == 0)
00376         {
00377             continue;
00378         }
00379 
00380         /* Create the new version directory. */
00381         mkdir(tmp2, 0755);
00382 
00383         /* Migrate 2.0 to 2.5. */
00384         if (!strcmp(client_versions[i], "2.0"))
00385         {
00386             upgrade_20_to_25(tmp, tmp2);
00387         }
00388     }
00389 }