UFO: Alien Invasion
Loading...
Searching...
No Matches
sv_mapcycle.cpp
Go to the documentation of this file.
1#include "server.h"
2#include "../shared/parse.h"
3
7typedef struct mapcycle_s {
8 char* map;
9 char* type;
10 bool day;
11 struct mapcycle_s* next;
13
15static int mapcycleCount;
16
20void SV_NextMapcycle (void)
21{
22 const char* map = nullptr, *gameType = nullptr;
23 bool day = true;
24 char expanded[MAX_QPATH];
25 mapcycle_t* mapcycle = mapcycleList;
26
27 if (sv->name[0]) {
28 Com_Printf("current map: %s\n", sv->name);
29 for (int i = 0; i < mapcycleCount; i++) {
30 /* random maps may have a theme - but that's not stored in sv->name
31 * but in sv->assembly */
32 if (mapcycle->map[0] == '+') {
33 Q_strncpyz(expanded, mapcycle->map, sizeof(expanded));
34 char* base = strstr(expanded, " ");
35 if (base) {
36 char assembly[MAX_QPATH];
37 base[0] = '\0'; /* split the strings */
38 Q_strncpyz(assembly, base + 1, sizeof(assembly));
39 /* get current position */
40 if (Q_streq(sv->name, expanded) && Q_streq(sv->assembly, assembly)) {
41 /* next map in cycle */
42 if (mapcycle->next) {
43 map = mapcycle->next->map;
44 day = mapcycle->next->day;
45 gameType = mapcycle->next->type;
46 Com_DPrintf(DEBUG_SERVER, "SV_NextMapcycle: next one: '%s' (gametype: %s)\n", map, gameType);
47 /* switch back to first list on cycle - if there is one */
48 } else {
49 map = mapcycleList->map;
50 day = mapcycleList->day;
51 gameType = mapcycleList->type;
52 Com_DPrintf(DEBUG_SERVER, "SV_NextMapcycle: first one: '%s' (gametype: %s)\n", map, gameType);
53 }
54 break;
55 }
56 } else {
57 Com_Printf("ignore mapcycle entry for random map (%s) with"
58 " no assembly given\n", mapcycle->map);
59 }
60 } else {
61 /* get current position */
62 if (Q_streq(sv->name, mapcycle->map)) {
63 /* next map in cycle */
64 if (mapcycle->next) {
65 map = mapcycle->next->map;
66 day = mapcycle->next->day;
67 gameType = mapcycle->next->type;
68 Com_DPrintf(DEBUG_SERVER, "SV_NextMapcycle: next one: '%s' (gametype: %s)\n", map, gameType);
69 /* switch back to first list on cycle - if there is one */
70 } else {
71 map = mapcycleList->map;
72 day = mapcycleList->day;
73 gameType = mapcycleList->type;
74 Com_DPrintf(DEBUG_SERVER, "SV_NextMapcycle: first one: '%s' (gametype: %s)\n", map, gameType);
75 }
76 Com_sprintf(expanded, sizeof(expanded), "maps/%s.bsp", map);
77
78 /* check for bsp file */
79 if (map[0] != '+' && FS_CheckFile("%s", expanded) < 0) {
80 Com_Printf("SV_NextMapcycle: Can't find '%s' - mapcycle error\n"
81 "Use the 'maplist' command to get a list of valid maps\n", expanded);
82 map = nullptr;
83 gameType = nullptr;
84 } else
85 break;
86 }
87 }
88 mapcycle = mapcycle->next;
89 }
90 }
91
92 if (!map) {
93 if (mapcycleCount > 0) {
94 map = mapcycleList->map;
95 day = mapcycleList->day;
96 gameType = mapcycleList->type;
97 if (map[0] != '+') {
98 Com_sprintf(expanded, sizeof(expanded), "maps/%s.bsp", map);
99
100 /* check for bsp file */
101 if (FS_CheckFile("%s", expanded) < 0) {
102 Com_Printf("SV_NextMapcycle: Can't find '%s' - mapcycle error\n"
103 "Use the 'maplist' command to get a list of valid maps\n", expanded);
104 return;
105 }
106 }
107 } else if (sv->name[0]) {
108 Com_Printf("No mapcycle - restart the current map (%s)\n", sv->name);
109 map = sv->name;
110 gameType = nullptr;
111 } else {
112 Com_Printf("No mapcycle and no running map\n");
113 return;
114 }
115 /* still not set? */
116 if (!map)
117 return;
118 }
119
120 /* check whether we want to change the gametype, too */
121 if (gameType && gameType[0] != '\0') {
122 Cvar_Set("sv_gametype", "%s", gameType);
124 sv_gametype->modified = false;
125 }
126
127 if (day)
128 Cbuf_AddText("map day %s", map);
129 else
130 Cbuf_AddText("map night %s", map);
131}
132
138{
139 mapcycle_t* mapcycle = mapcycleList;
140
141 for (int i = 0; i < mapcycleCount; i++) {
142 mapcycle_t* oldMapcycle = mapcycle;
143 mapcycle = mapcycle->next;
144 Mem_Free(oldMapcycle->type);
145 Mem_Free(oldMapcycle->map);
146 Mem_Free(oldMapcycle);
147 }
148
149 /* reset the mapcycle data */
150 mapcycleList = nullptr;
151 mapcycleCount = 0;
152}
153
159static void SV_MapcycleAdd (const char* mapName, bool day, const char* gameType)
160{
162 mapcycle->map = Mem_PoolStrDup(mapName, sv_genericPool, 0);
163 mapcycle->day = day;
164 mapcycle->type = Mem_PoolStrDup(gameType, sv_genericPool, 0);
165 mapcycle->next = 0;
166 Com_DPrintf(DEBUG_SERVER, "mapcycle add: '%s' type '%s'\n", mapcycle->map, mapcycle->type);
167
168 /* Append to end of list. */
169 mapcycle_t** anchor = &mapcycleList;
170 while (*anchor) anchor = &(*anchor)->next;
171 *anchor = mapcycle;
172
174}
175
181static void SV_ParseMapcycle (void)
182{
183 int length = 0;
184 byte* buffer = nullptr;
185 const char* buf;
186
187 mapcycleCount = 0;
188 mapcycleList = nullptr;
189
190 length = FS_LoadFile("mapcycle.txt", &buffer);
191 if (length == -1 || !buffer)
192 return;
193
194 if (length != -1) {
195 buf = (const char*)buffer;
196 do {
197 bool day = false;
198 const char* token;
199 char map[MAX_VAR], gameType[MAX_VAR];
200 /* parse map name */
201 token = Com_Parse(&buf);
202 if (!buf)
203 break;
204 Q_strncpyz(map, token, sizeof(map));
205 /* parse day or night */
206 token = Com_Parse(&buf);
207 if (!buf)
208 break;
209 if (Q_streq(token, "day"))
210 day = true;
211 else if (!Q_streq(token, "night")) {
212 Com_Printf("Skip mapcycle parsing, expected day or night.");
213 break;
214 }
215 /* parse gametype */
216 token = Com_Parse(&buf);
217 if (!buf)
218 break;
219 Q_strncpyz(gameType, token, sizeof(gameType));
220 SV_MapcycleAdd(map, day, gameType);
221 } while (buf);
222
223 Com_Printf("added %i maps to the mapcycle\n", mapcycleCount);
224 }
225 FS_FreeFile(buffer);
226}
227
228static void SV_MapcycleList_f (void)
229{
230 const mapcycle_t* mapcycle = mapcycleList;
231
232 Com_Printf("current mapcycle has %i entries\n", mapcycleCount);
233 for (int i = 0; i < mapcycleCount; i++) {
234 Com_Printf(" %s (%s)\n", mapcycle->map, mapcycle->type);
235 mapcycle = mapcycle->next;
236 }
237}
238
239static void SV_MapcycleAdd_f (void)
240{
241 if (Cmd_Argc() == 4) {
242 const char* map = Cmd_Argv(1);
243 const char* day = Cmd_Argv(2);
244 const char* gametype = Cmd_Argv(3);
245 if (!SV_CheckMap(map, nullptr)) {
246 Com_Printf("map '%s' isn't a valid map\n", map);
247 return;
248 }
249 Com_Printf("adding map '%s' with gametype '%s' to mapcycle (to add this permanently edit your mapcycle.txt)\n", map, gametype);
250 if (Q_streq(day, "day"))
251 SV_MapcycleAdd(map, true, gametype);
252 else
253 SV_MapcycleAdd(map, false, gametype);
254 } else {
255 Com_Printf("Usage: %s <mapname> <day|night> <gametype>\n", Cmd_Argv(0));
256 Com_Printf(" ...to get a list of valid maps type 'maplist'\n"
257 " ...to get a list of valid gametypes 'gametypelist'\n");
258 }
259}
260
261static void SV_MapcycleNext_f (void)
262{
263 if (mapcycleCount > 0)
265 else
266 Com_Printf("no mapcycle.txt\n");
267}
268
270{
272
273 Cmd_AddCommand("mapcyclelist", SV_MapcycleList_f, "Print the current mapcycle");
274 Cmd_AddCommand("mapcyclenext", SV_MapcycleNext_f, "Start the next map from the cycle");
275 Cmd_AddCommand("mapcycleclear", SV_MapcycleClear, "Delete the current mapcycle");
276 Cmd_AddCommand("mapcycleadd", SV_MapcycleAdd_f, "Add new maps to the mapcycle");
277}
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition cmd.cpp:516
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
Definition cmd.cpp:505
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
Definition cmd.cpp:744
void Cbuf_AddText(const char *format,...)
Adds command text at the end of the buffer.
Definition cmd.cpp:126
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition common.cpp:440
void Com_SetGameType(void)
Definition common.cpp:832
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
cvar_t * sv_gametype
Definition common.cpp:56
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition cvar.cpp:615
#define DEBUG_SERVER
Definition defines.h:60
int FS_CheckFile(const char *fmt,...)
Just returns the filelength and -1 if the file wasn't found.
Definition files.cpp:298
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition files.cpp:384
void FS_FreeFile(void *buffer)
Definition files.cpp:411
#define MAX_QPATH
Definition filesys.h:40
voidpf void * buf
Definition ioapi.h:42
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_PoolStrDup(in, pool, tagNum)
Definition mem.h:50
#define Mem_PoolAllocType(type, pool)
Definition mem.h:43
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition parse.cpp:107
Shared parsing functions.
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition r_gl.h:110
QGL_EXTERN GLint i
Definition r_gl.h:113
Main server include file.
memPool_t * sv_genericPool
Definition sv_main.cpp:55
void SV_MapcycleClear(void)
Empty the mapcycle list.
bool SV_CheckMap(const char *map, const char *assembly)
Checks whether a map exists.
Definition sv_ccmds.cpp:101
serverInstanceGame_t * sv
Definition sv_init.cpp:36
#define Q_streq(a, b)
Definition shared.h:136
#define MAX_VAR
Definition shared.h:36
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
map cycle list element
struct mapcycle_s * next
char * type
void SV_MapcycleClear(void)
Empty the mapcycle list.
static void SV_MapcycleNext_f(void)
void SV_MapcycleInit(void)
static void SV_MapcycleAdd(const char *mapName, bool day, const char *gameType)
Append a new mapname to the list of maps for the cycle.
static void SV_ParseMapcycle(void)
Parses the server mapcycle.
void SV_NextMapcycle(void)
Start the next map in the cycle.
static void SV_MapcycleAdd_f(void)
static void SV_MapcycleList_f(void)
static int mapcycleCount
static mapcycle_t * mapcycleList
static const char * mapName