Crossfire Client, Branch  R11627
init.c
Go to the documentation of this file.
00001 const char * const rcsid_common_init_c =
00002     "$Id: init.c 10973 2008-12-14 08:51:26Z ryo_saeba $";
00003 /*
00004     Crossfire client, a client program for the crossfire program.
00005 
00006     Copyright (C) 2001 Mark Wedel & Crossfire Development Team
00007 
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with this program; if not, write to the Free Software
00020     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021 
00022     The author can be reached via e-mail to crossfire-devel@real-time.com
00023 */
00024 
00025 /* This handles the initialization of the client.  This includes making
00026  * the I_IMAGE and I_ARCH commands.
00027  */
00028 
00029 #include <client.h>
00030 #include "p_cmd.h" /* init_commands() */
00031 
00032 /* XXX Does the x11 client *use* these? */
00033 
00034 /* Makes the load/save code trivial - basically, the
00035  * entries here match the same numbers as the CONFIG_ values defined
00036  * in common/client.h - this means the load and save just does
00037  * something like a fprintf(outifle, "%s: %d", config_names[i],
00038  *                          want_config[i]);
00039  */
00040 const char *const config_names[CONFIG_NUMS] = {
00041 NULL, "download_all_images", "echo_bindings",
00042 "fasttcpsend", "command_window", "cacheimages", "fog_of_war", "iconscale",
00043 "mapscale", "popups", "displaymode", "showicon", "tooltips", "sound", "splitinfo",
00044 "split", "show_grid", "lighting", "trim_info_window",
00045 "map_width", "map_height", "foodbeep", "darkness", "port",
00046 "grad_color_bars", "resistances", "smoothing", "nosplash",
00047 "auto_apply_container", "mapscroll", "sign_popups", "message_timestamping"
00048 };
00049 
00050 sint16 want_config[CONFIG_NUMS], use_config[CONFIG_NUMS];
00051 
00052 #define FREE_AND_CLEAR(xyz) { free(xyz); xyz=NULL; }
00053 
00054 void VersionCmd(char *data, int len)
00055 {
00056     char *cp;
00057 
00058     csocket.cs_version = atoi(data);
00059     /* set sc_version in case it is an old server supplying only one version */
00060     csocket.sc_version = csocket.cs_version;
00061     if (csocket.cs_version != VERSION_CS) {
00062         LOG(LOG_WARNING,"common::VersionCmd","Differing C->S version numbers (%d,%d)",
00063             VERSION_CS,csocket.cs_version);
00064 /*      exit(1);*/
00065     }
00066     cp = strchr(data,' ');
00067     if (!cp) return;
00068     csocket.sc_version = atoi(cp);
00069     if (csocket.sc_version != VERSION_SC) {
00070     LOG(LOG_WARNING,"common::VersionCmd","Differing S->C version numbers (%d,%d)",
00071         VERSION_SC,csocket.sc_version);
00072     }
00073     cp = strchr(cp+1, ' ');
00074     if (cp)
00075         LOG(LOG_INFO,"common::VersionCmd","Playing on server type %s", cp);
00076 }
00077 
00078 void SendVersion(ClientSocket csock)
00079 {
00080     cs_print_string(csock.fd,
00081                     "version %d %d %s", VERSION_CS, VERSION_SC, VERSION_INFO);
00082 }
00083 
00084 
00085 void SendAddMe(ClientSocket csock)
00086 {
00087     cs_print_string(csock.fd, "addme");
00088 }
00089 
00090 
00091 void SendSetFaceMode(ClientSocket csock,int mode)
00092 {
00093     cs_print_string(csock.fd, "setfacemode %d", mode);
00094 }
00095 
00096 
00097 void init_client_vars(void)
00098 {
00099     int i;
00100 
00101     /* I think environment variables should be more important than
00102      * compiled in defaults, so these probably should be reversed.
00103      */
00104     client_libdir=getenv("CFCLIENT_LIBDIR");
00105 #ifdef CLIENT_LIBDIR
00106     if (client_libdir==NULL)
00107         client_libdir=CLIENT_LIBDIR;
00108 #endif
00109 
00110     if (exp_table) {
00111         free(exp_table);
00112         exp_table=NULL;
00113     }
00114     exp_table_max=0;
00115 
00116     cpl.count_left = 0;
00117     cpl.container = NULL;
00118     memset(&cpl.stats,0, sizeof(Stats));
00119     cpl.stats.maxsp=1;  /* avoid div by 0 errors */
00120     cpl.stats.maxhp=1;  /* ditto */
00121     cpl.stats.maxgrace=1;       /* ditto */
00122     /* ditto - displayed weapon speed is weapon speed/speed */
00123     cpl.stats.speed=1;
00124     cpl.input_text[0]='\0';
00125     cpl.title[0] = '\0';
00126     cpl.range[0] = '\0';
00127     cpl.last_command[0] = '\0';
00128 
00129     for (i=0; i<range_size; i++)
00130         cpl.ranges[i]=NULL;
00131 
00132     for (i=0; i<MAX_SKILL; i++) {
00133         cpl.stats.skill_exp[i]=0;
00134         cpl.stats.skill_level[i] = 0;
00135         skill_names[i] = NULL;
00136         last_used_skills[i] = -1;
00137     }
00138         last_used_skills[MAX_SKILL] = -1;
00139 
00140     cpl.ob = player_item();
00141     cpl.below = map_item();
00142     cpl.magicmap=NULL;
00143     cpl.showmagic=0;
00144 
00145 
00146     csocket.command_sent=0;
00147     csocket.command_received=0;
00148     csocket.command_time=0;
00149 
00150     face_info.faceset = 0;
00151     face_info.num_images = 0;
00152     face_info.bmaps_checksum = 0;
00153     face_info.old_bmaps_checksum = 0;
00154     face_info.want_faceset = NULL;
00155     face_info.cache_hits=0;
00156     face_info.cache_misses=0;
00157     face_info.have_faceset_info=0;
00158     for (i=0; i<MAX_FACE_SETS; i++) {
00159         face_info.facesets[i].prefix = NULL;
00160         face_info.facesets[i].fullname = NULL;
00161         face_info.facesets[i].fallback = 0;
00162         face_info.facesets[i].size = NULL;
00163         face_info.facesets[i].extension = NULL;
00164         face_info.facesets[i].comment = NULL;
00165     }
00166     /* Makes just as much sense to initialize the arrays
00167      * where they are declared, but I did this so I could
00168      * keep track of everything as I was updating
00169      * the code.  Plus, the performance difference is virtually
00170      * nothing.
00171      */
00172     want_config[CONFIG_DOWNLOAD] = FALSE;
00173     want_config[CONFIG_ECHO] = FALSE;
00174     want_config[CONFIG_FASTTCP] = TRUE;
00175     want_config[CONFIG_CWINDOW] = COMMAND_WINDOW;
00176     want_config[CONFIG_CACHE] = FALSE;
00177     want_config[CONFIG_FOGWAR] = TRUE;
00178     want_config[CONFIG_ICONSCALE] = 100;
00179     want_config[CONFIG_MAPSCALE] = 100;
00180     want_config[CONFIG_POPUPS] = FALSE;
00181     want_config[CONFIG_DISPLAYMODE] = CFG_DM_PIXMAP;
00182     want_config[CONFIG_SHOWICON] = FALSE;
00183     want_config[CONFIG_TOOLTIPS] = TRUE;
00184     want_config[CONFIG_SOUND] = TRUE;
00185     want_config[CONFIG_SPLITINFO] = FALSE;
00186     want_config[CONFIG_SPLITWIN] = FALSE;
00187     want_config[CONFIG_SHOWGRID] = FALSE;
00188     want_config[CONFIG_LIGHTING] = CFG_LT_TILE;
00189     want_config[CONFIG_TRIMINFO] = FALSE;
00190     want_config[CONFIG_MAPWIDTH] = 11;
00191     want_config[CONFIG_MAPHEIGHT] = 11;
00192     want_config[CONFIG_FOODBEEP] = FALSE;
00193     want_config[CONFIG_DARKNESS] = TRUE;
00194     want_config[CONFIG_PORT] = EPORT;
00195     want_config[CONFIG_GRAD_COLOR] = FALSE;
00196     want_config[CONFIG_RESISTS] = 0;
00197     want_config[CONFIG_RESISTS] = 0;
00198     want_config[CONFIG_SMOOTH] = 0;
00199     want_config[CONFIG_SPLASH] = TRUE;
00200     want_config[CONFIG_APPLY_CONTAINER] = TRUE;     /* Same behavior before this option was put in */
00201     want_config[CONFIG_MAPSCROLL] = TRUE;
00202     want_config[CONFIG_SIGNPOPUP] = TRUE;
00203     want_config[CONFIG_TIMESTAMP] = FALSE;
00204     for (i=0; i<CONFIG_NUMS; i++)
00205         use_config[i] = want_config[i];
00206 
00207 #ifdef WIN32
00208     /* If HOME is not set, let's set it to . to avoid things like (null)/.crossfire paths */
00209     if ( !getenv( "HOME" ) )
00210         {
00211         if ( getenv( "APPDATA" ) )
00212             {
00213             char env[ MAX_BUF ];
00214             _snprintf( env, MAX_BUF, "HOME=%s", getenv( "APPDATA" ) );
00215             LOG( LOG_INFO, "common::init.c", "init_client_vars: HOME set to %APPDATA%.\n" );
00216             putenv( env );
00217             }
00218         else
00219             {
00220             LOG( LOG_INFO, "common::init.c", "init_client_vars: HOME not set, setting it to .\n" );
00221             putenv( "HOME=." );
00222             }
00223         }
00224 #endif
00225     init_commands(); /* pcmd.c */
00226     init_metaserver();  /* metaserver.c */
00227     /* Any reasonable seed really works */
00228     srandom(time(NULL));
00229 }
00230 
00231 /* This is basically called each time a new player logs
00232  * on - reset all the player data
00233  */
00234 void reset_player_data(void)
00235 {
00236     int i;
00237 
00238     for (i=0; i<MAX_SKILL; i++) {
00239         cpl.stats.skill_exp[i]=0;
00240         cpl.stats.skill_level[i] = 0;
00241     }
00242 }
00243 
00244 /* This is used to clear values between connections to different
00245  * servers.  This needs to be called after init_client_vars has
00246  * been called because it does not re-allocated some values.
00247  */
00248 
00249 void reset_client_vars(void)
00250 {
00251     int i;
00252 
00253     cpl.count_left = 0;
00254     cpl.container = NULL;
00255     memset(&cpl.stats,0, sizeof(Stats));
00256     cpl.stats.maxsp=1;  /* avoid div by 0 errors */
00257     cpl.stats.maxhp=1;  /* ditto */
00258     cpl.stats.maxgrace=1;       /* ditto */
00259     /* ditto - displayed weapon speed is weapon speed/speed */
00260     cpl.stats.speed=1;
00261     cpl.input_text[0]='\0';
00262     cpl.title[0] = '\0';
00263     cpl.range[0] = '\0';
00264     cpl.last_command[0] = '\0';
00265 
00266     for (i=0; i<range_size; i++)
00267         cpl.ranges[i]=NULL;
00268 
00269     cpl.magicmap=NULL;
00270     cpl.showmagic=0;
00271 
00272     csocket.command_sent=0;
00273     csocket.command_received=0;
00274     csocket.command_time=0;
00275 
00276     face_info.faceset = 0;
00277     face_info.num_images = 0;
00278     /* Preserve the old one - this can be used to see if the next
00279      * server has the same name -> number mapping so that we don't
00280      * need to rebuild all the images.
00281      */
00282     face_info.old_bmaps_checksum = face_info.bmaps_checksum;
00283     face_info.bmaps_checksum = 0;
00284     face_info.cache_hits=0;
00285     face_info.cache_misses=0;
00286     face_info.have_faceset_info=0;
00287     for (i=0; i<MAX_FACE_SETS; i++) {
00288         FREE_AND_CLEAR(face_info.facesets[i].prefix);
00289         FREE_AND_CLEAR(face_info.facesets[i].fullname);
00290         face_info.facesets[i].fallback = 0;
00291         FREE_AND_CLEAR(face_info.facesets[i].size);
00292         FREE_AND_CLEAR(face_info.facesets[i].extension);
00293         FREE_AND_CLEAR(face_info.facesets[i].comment);
00294     }
00295     reset_player_data();
00296     for (i=0; i<MAX_SKILL; i++)
00297         FREE_AND_CLEAR(skill_names[i]);
00298 
00299 }