sv_mapcycle.c

Go to the documentation of this file.
00001 #include "server.h"
00002 #include "../shared/parse.h"
00003 
00007 typedef struct mapcycle_s {
00008     char *map;          
00009     char *type;         
00010     qboolean day;       
00011     struct mapcycle_s* next;    
00012 } mapcycle_t;
00013 
00014 static mapcycle_t *mapcycleList;    
00015 static int mapcycleCount;       
00020 void SV_NextMapcycle (void)
00021 {
00022     const char *map = NULL, *gameType = NULL;
00023     qboolean day = qtrue;
00024     char *base;
00025     char assembly[MAX_QPATH];
00026     char expanded[MAX_QPATH];
00027     char cmd[MAX_QPATH];
00028     mapcycle_t *mapcycle;
00029 
00030     mapcycle = mapcycleList;
00031     if (sv.name[0]) {
00032         int i;
00033         Com_Printf("current map: %s\n", sv.name);
00034         for (i = 0; i < mapcycleCount; i++) {
00035             /* random maps may have a theme - but that's not stored in sv.name
00036              * but in sv.assembly */
00037             if (mapcycle->map[0] == '+') {
00038                 Q_strncpyz(expanded, mapcycle->map, sizeof(expanded));
00039                 base = strstr(expanded, " ");
00040                 if (base) {
00041                     base[0] = '\0'; /* split the strings */
00042                     Q_strncpyz(assembly, base + 1, sizeof(assembly));
00043                     /* get current position */
00044                     if (!strcmp(sv.name, expanded) && !strcmp(sv.assembly, assembly)) {
00045                         /* next map in cycle */
00046                         if (mapcycle->next) {
00047                             map = mapcycle->next->map;
00048                             day = mapcycle->next->day;
00049                             gameType = mapcycle->next->type;
00050                             Com_DPrintf(DEBUG_SERVER, "SV_NextMapcycle: next one: '%s' (gametype: %s)\n", map, gameType);
00051                         /* switch back to first list on cycle - if there is one */
00052                         } else {
00053                             map = mapcycleList->map;
00054                             day = mapcycleList->day;
00055                             gameType = mapcycleList->type;
00056                             Com_DPrintf(DEBUG_SERVER, "SV_NextMapcycle: first one: '%s' (gametype: %s)\n", map, gameType);
00057                         }
00058                         break;
00059                     }
00060                 } else {
00061                     Com_Printf("ignore mapcycle entry for random map (%s) with"
00062                         " no assembly given\n", mapcycle->map);
00063                 }
00064             } else {
00065                 /* get current position */
00066                 if (!strcmp(sv.name, mapcycle->map)) {
00067                     /* next map in cycle */
00068                     if (mapcycle->next) {
00069                         map = mapcycle->next->map;
00070                         day = mapcycle->next->day;
00071                         gameType = mapcycle->next->type;
00072                         Com_DPrintf(DEBUG_SERVER, "SV_NextMapcycle: next one: '%s' (gametype: %s)\n", map, gameType);
00073                     /* switch back to first list on cycle - if there is one */
00074                     } else {
00075                         map = mapcycleList->map;
00076                         day = mapcycleList->day;
00077                         gameType = mapcycleList->type;
00078                         Com_DPrintf(DEBUG_SERVER, "SV_NextMapcycle: first one: '%s' (gametype: %s)\n", map, gameType);
00079                     }
00080                     Com_sprintf(expanded, sizeof(expanded), "maps/%s.bsp", map);
00081 
00082                     /* check for bsp file */
00083                     if (map[0] != '+' && FS_CheckFile("%s", expanded) < 0) {
00084                         Com_Printf("SV_NextMapcycle: Can't find '%s' - mapcycle error\n"
00085                             "Use the 'maplist' command to get a list of valid maps\n", expanded);
00086                         map = NULL;
00087                         gameType = NULL;
00088                     } else
00089                         break;
00090                 }
00091             }
00092             mapcycle = mapcycle->next;
00093         }
00094     }
00095 
00096     if (!map) {
00097         if (mapcycleCount > 0) {
00098             map = mapcycleList->map;
00099             day = mapcycleList->day;
00100             gameType = mapcycleList->type;
00101             if (map[0] != '+') {
00102                 Com_sprintf(expanded, sizeof(expanded), "maps/%s.bsp", map);
00103 
00104                 /* check for bsp file */
00105                 if (FS_CheckFile("%s", expanded) < 0) {
00106                     Com_Printf("SV_NextMapcycle: Can't find '%s' - mapcycle error\n"
00107                         "Use the 'maplist' command to get a list of valid maps\n", expanded);
00108                     return;
00109                 }
00110             }
00111         } else if (sv.name[0]) {
00112             Com_Printf("No mapcycle - restart the current map (%s)\n", sv.name);
00113             map = sv.name;
00114             gameType = NULL;
00115         } else {
00116             Com_Printf("No mapcycle and no running map\n");
00117             return;
00118         }
00119         /* still not set? */
00120         if (!map)
00121             return;
00122     }
00123 
00124     /* check whether we want to change the gametype, too */
00125     if (gameType && gameType[0] != '\0') {
00126         Cvar_Set("sv_gametype", gameType);
00127         Com_SetGameType();
00128         sv_gametype->modified = qfalse;
00129     }
00130 
00131     if (day)
00132         Com_sprintf(cmd, sizeof(cmd), "map day %s", map);
00133     else
00134         Com_sprintf(cmd, sizeof(cmd), "map night %s", map);
00135     Cbuf_AddText(cmd);
00136 }
00137 
00142 void SV_MapcycleClear (void)
00143 {
00144     int i;
00145     mapcycle_t *mapcycle;
00146 
00147     mapcycle = mapcycleList;
00148     for (i = 0; i < mapcycleCount; i++) {
00149         mapcycle_t *oldMapcycle = mapcycle;
00150         mapcycle = mapcycle->next;
00151         Mem_Free(oldMapcycle->type);
00152         Mem_Free(oldMapcycle->map);
00153         Mem_Free(oldMapcycle);
00154     }
00155 
00156     /* reset the mapcycle data */
00157     mapcycleList = NULL;
00158     mapcycleCount = 0;
00159 }
00160 
00166 static void SV_MapcycleAdd (const char* mapName, qboolean day, const char* gameType)
00167 {
00168     mapcycle_t *mapcycle;
00169 
00170     if (!mapcycleList) {
00171         mapcycleList = Mem_PoolAlloc(sizeof(*mapcycle), sv_genericPool, 0);
00172         mapcycle = mapcycleList; /* first one */
00173     } else {
00174         /* go to the last entry */
00175         mapcycle = mapcycleList;
00176         while (mapcycle->next)
00177             mapcycle = mapcycle->next;
00178         mapcycle->next = Mem_PoolAlloc(sizeof(*mapcycle), sv_genericPool, 0);
00179         mapcycle = mapcycle->next;
00180     }
00181     mapcycle->map = Mem_PoolStrDup(mapName, sv_genericPool, 0);
00182     mapcycle->day = day;
00183     mapcycle->type = Mem_PoolStrDup(gameType, sv_genericPool, 0);
00184     Com_DPrintf(DEBUG_SERVER, "mapcycle add: '%s' type '%s'\n", mapcycle->map, mapcycle->type);
00185     mapcycle->next = NULL;
00186     mapcycleCount++;
00187 }
00188 
00194 static void SV_ParseMapcycle (void)
00195 {
00196     int length = 0;
00197     byte *buffer = NULL;
00198     const char *token;
00199     const char *buf;
00200     char map[MAX_VAR], gameType[MAX_VAR];
00201 
00202     mapcycleCount = 0;
00203     mapcycleList = NULL;
00204 
00205     length = FS_LoadFile("mapcycle.txt", &buffer);
00206     if (length == -1 || !buffer)
00207         return;
00208 
00209     if (length != -1) {
00210         buf = (const char*)buffer;
00211         do {
00212             qboolean day = qfalse;
00213             /* parse map name */
00214             token = Com_Parse(&buf);
00215             if (!buf)
00216                 break;
00217             Q_strncpyz(map, token, sizeof(map));
00218             /* parse day or night */
00219             token = Com_Parse(&buf);
00220             if (!buf)
00221                 break;
00222             if (!strcmp(token, "day"))
00223                 day = qtrue;
00224             else if (strcmp(token, "night")) {
00225                 Com_Printf("Skip mapcycle parsing, expected day or night.");
00226                 break;
00227             }
00228             /* parse gametype */
00229             token = Com_Parse(&buf);
00230             if (!buf)
00231                 break;
00232             Q_strncpyz(gameType, token, sizeof(gameType));
00233             SV_MapcycleAdd(map, day, gameType);
00234         } while (buf);
00235 
00236         Com_Printf("added %i maps to the mapcycle\n", mapcycleCount);
00237     }
00238     FS_FreeFile(buffer);
00239 }
00240 
00241 static void SV_MapcycleList_f (void)
00242 {
00243     int i;
00244     const mapcycle_t* mapcycle;
00245 
00246     mapcycle = mapcycleList;
00247     Com_Printf("current mapcycle has %i entries\n", mapcycleCount);
00248     for (i = 0; i < mapcycleCount; i++) {
00249         Com_Printf(" %s (%s)\n", mapcycle->map, mapcycle->type);
00250         mapcycle = mapcycle->next;
00251     }
00252 }
00253 
00254 static void SV_MapcycleAdd_f (void)
00255 {
00256     if (Cmd_Argc() == 4) {
00257         const char *map = Cmd_Argv(1);
00258         const char *day = Cmd_Argv(2);
00259         const char *gametype = Cmd_Argv(3);
00260         if (!SV_CheckMap(map, NULL)) {
00261             Com_Printf("map '%s' isn't a valid map\n", map);
00262             return;
00263         }
00264         Com_Printf("adding map '%s' with gametype '%s' to mapcycle (to add this permanently edit your mapcycle.txt)\n", map, gametype);
00265         if (!strcmp(day, "day"))
00266             SV_MapcycleAdd(map, qtrue, gametype);
00267         else
00268             SV_MapcycleAdd(map, qfalse, gametype);
00269     } else {
00270         Com_Printf("Usage: %s <mapname> <day|night> <gametype>\n", Cmd_Argv(0));
00271         Com_Printf(" ...to get a list of valid maps type 'maplist'\n"
00272             " ...to get a list of valid gametypes 'gametypelist'\n");
00273     }
00274 }
00275 
00276 static void SV_MapcycleNext_f (void)
00277 {
00278     if (mapcycleCount > 0)
00279         SV_NextMapcycle();
00280     else
00281         Com_Printf("no mapcycle.txt\n");
00282 }
00283 
00284 void SV_MapcycleInit (void)
00285 {
00286     SV_ParseMapcycle();
00287 
00288     Cmd_AddCommand("mapcyclelist", SV_MapcycleList_f, "Print the current mapcycle");
00289     Cmd_AddCommand("mapcyclenext", SV_MapcycleNext_f, "Start the next map from the cycle");
00290     Cmd_AddCommand("mapcycleclear", SV_MapcycleClear, "Delete the current mapcycle");
00291     Cmd_AddCommand("mapcycleadd", SV_MapcycleAdd_f, "Add new maps to the mapcycle");
00292 }

Generated by  doxygen 1.6.2