… | |
… | |
215 | |
215 | |
216 | LOG (llevDebug, "Assigned %u regions with %u parents.\n", region_count, parent_count); |
216 | LOG (llevDebug, "Assigned %u regions with %u parents.\n", region_count, parent_count); |
217 | } |
217 | } |
218 | |
218 | |
219 | /* |
219 | /* |
|
|
220 | * Reads/parses the region file, and copies into a linked list |
|
|
221 | * of region structs. |
|
|
222 | */ |
|
|
223 | static bool |
|
|
224 | parse_regions (object_thawer &fp) |
|
|
225 | { |
|
|
226 | region *newreg; |
|
|
227 | region *reg; |
|
|
228 | |
|
|
229 | newreg = NULL; |
|
|
230 | for (;;) |
|
|
231 | { |
|
|
232 | keyword kw = fp.get_kv (); |
|
|
233 | |
|
|
234 | switch (kw) |
|
|
235 | { |
|
|
236 | case KW_EOF: |
|
|
237 | if (newreg) |
|
|
238 | { |
|
|
239 | LOG (llevError, "%s: end of file while reading regions.\n", fp.name); |
|
|
240 | return false; |
|
|
241 | } |
|
|
242 | else |
|
|
243 | return true; |
|
|
244 | |
|
|
245 | case KW_end: |
|
|
246 | /* Place this new region last on the list, if the list is empty put it first */ |
|
|
247 | for (reg = first_region; reg && reg->next; reg = reg->next) |
|
|
248 | ; |
|
|
249 | |
|
|
250 | if (!reg) |
|
|
251 | first_region = newreg; |
|
|
252 | else |
|
|
253 | reg->next = newreg; |
|
|
254 | |
|
|
255 | newreg = 0; |
|
|
256 | break; |
|
|
257 | |
|
|
258 | default: |
|
|
259 | case KW_ERROR: |
|
|
260 | LOG (llevError, "%s: skipping errornous line (%s) while reading regions.\n", fp.name, fp.last_keyword); |
|
|
261 | break; |
|
|
262 | |
|
|
263 | case KW_region: |
|
|
264 | newreg = new region; |
|
|
265 | fp.get (newreg->name); |
|
|
266 | break; |
|
|
267 | |
|
|
268 | case KW_parent: |
|
|
269 | /* |
|
|
270 | * Note that this is in the initialisation code, so we don't actually |
|
|
271 | * assign the pointer to the parent yet, because it might not have been |
|
|
272 | * parsed. |
|
|
273 | */ |
|
|
274 | fp.get (newreg->parent_name); |
|
|
275 | break; |
|
|
276 | |
|
|
277 | case KW_longname: |
|
|
278 | newreg->longname = strdup (fp.get_str ()); |
|
|
279 | break; |
|
|
280 | |
|
|
281 | case KW_jail_map: |
|
|
282 | fp.get (newreg->jailmap); |
|
|
283 | break; |
|
|
284 | |
|
|
285 | case KW_jail_x: |
|
|
286 | fp.get (newreg->jailx); |
|
|
287 | break; |
|
|
288 | |
|
|
289 | case KW_jail_y: |
|
|
290 | fp.get (newreg->jaily); |
|
|
291 | break; |
|
|
292 | |
|
|
293 | case KW_msg: |
|
|
294 | fp.get_ml (KW_endmsg, newreg->msg); |
|
|
295 | break; |
|
|
296 | |
|
|
297 | case KW_fallback: |
|
|
298 | fp.get (newreg->fallback); |
|
|
299 | break; |
|
|
300 | |
|
|
301 | case KW_nomore: |
|
|
302 | /* we have reached the end of the region specs.... */ |
|
|
303 | return true; |
|
|
304 | } |
|
|
305 | } |
|
|
306 | } |
|
|
307 | |
|
|
308 | /* |
220 | * First initialises the archtype hash-table (init_archetable()). |
309 | * First initialises the archtype hash-table (init_archetable()). |
221 | * Reads and parses the archetype file (with the first and second-pass |
310 | * Reads and parses the archetype file (with the first and second-pass |
222 | * functions). |
311 | * functions). |
223 | * Then initialises treasures by calling load_treasures(). |
312 | * Then initialises treasures by calling load_treasures(). |
224 | */ |
313 | */ |
225 | void |
314 | void |
226 | init_regions (void) |
315 | init_regions (void) |
227 | { |
316 | { |
228 | FILE *fp; |
|
|
229 | char filename[MAX_BUF]; |
317 | char filename[MAX_BUF]; |
230 | int comp; |
318 | int comp; |
231 | |
319 | |
232 | if (first_region != NULL) /* Only do this once */ |
320 | if (first_region != NULL) /* Only do this once */ |
233 | return; |
321 | return; |
… | |
… | |
237 | first_region->name = "<builtin>"; |
325 | first_region->name = "<builtin>"; |
238 | first_region->longname = strdup ("Built-in Region"); |
326 | first_region->longname = strdup ("Built-in Region"); |
239 | |
327 | |
240 | sprintf (filename, "%s/%s/%s", settings.datadir, settings.mapdir, settings.regions); |
328 | sprintf (filename, "%s/%s/%s", settings.datadir, settings.mapdir, settings.regions); |
241 | LOG (llevDebug, "Reading regions from %s...\n", filename); |
329 | LOG (llevDebug, "Reading regions from %s...\n", filename); |
242 | if ((fp = open_and_uncompress (filename, 0, &comp)) == NULL) |
330 | |
|
|
331 | object_thawer fp (filename); |
|
|
332 | |
|
|
333 | if (!fp) |
243 | { |
334 | { |
244 | LOG (llevError, " Can't open regions file %s in init_regions.\n", filename); |
335 | LOG (llevError, " Can't open regions file %s in init_regions.\n", filename); |
245 | return; |
336 | return; |
246 | } |
337 | } |
247 | |
338 | |
248 | parse_regions (fp); |
339 | parse_regions (fp); |
|
|
340 | |
249 | assign_region_parents (); |
341 | assign_region_parents (); |
250 | LOG (llevDebug, " done\n"); |
342 | LOG (llevDebug, " done\n"); |
251 | |
|
|
252 | close_and_delete (fp, comp); |
|
|
253 | } |
343 | } |
254 | |
|
|
255 | /* |
|
|
256 | * Reads/parses the region file, and copies into a linked list |
|
|
257 | * of region structs. |
|
|
258 | */ |
|
|
259 | void |
|
|
260 | parse_regions (FILE * fp) |
|
|
261 | { |
|
|
262 | region *newreg; |
|
|
263 | region *reg; |
|
|
264 | |
|
|
265 | char buf[HUGE_BUF], msgbuf[HUGE_BUF], *key = NULL, *value, *end; |
|
|
266 | int msgpos = 0; |
|
|
267 | |
|
|
268 | newreg = NULL; |
|
|
269 | while (fgets (buf, HUGE_BUF - 1, fp) != NULL) |
|
|
270 | { |
|
|
271 | buf[HUGE_BUF - 1] = 0; |
|
|
272 | key = buf; |
|
|
273 | while (isspace (*key)) |
|
|
274 | key++; |
|
|
275 | if (*key == 0) |
|
|
276 | continue; /* empty line */ |
|
|
277 | value = strchr (key, ' '); |
|
|
278 | if (!value) |
|
|
279 | { |
|
|
280 | end = strchr (key, '\n'); |
|
|
281 | *end = 0; |
|
|
282 | } |
|
|
283 | else |
|
|
284 | { |
|
|
285 | *value = 0; |
|
|
286 | value++; |
|
|
287 | while (isspace (*value)) |
|
|
288 | value++; |
|
|
289 | end = strchr (value, '\n'); |
|
|
290 | } |
|
|
291 | |
|
|
292 | /* |
|
|
293 | * This is a bizzare mutated form of the map and archetype parser |
|
|
294 | * rolled into one. Key is the field name, value is what it should |
|
|
295 | * be set to. |
|
|
296 | * We've already done the work to null terminate key, |
|
|
297 | * and strip off any leading spaces for both of these. |
|
|
298 | * We have not touched the newline at the end of the line - |
|
|
299 | * these might be needed for some values. the end pointer |
|
|
300 | * points to the first of the newlines. |
|
|
301 | * value could be NULL! It would be easy enough to just point |
|
|
302 | * this to "" to prevent cores, but that would let more errors slide |
|
|
303 | * through. |
|
|
304 | */ |
|
|
305 | if (!strcmp (key, "region")) |
|
|
306 | { |
|
|
307 | *end = 0; |
|
|
308 | newreg = new region; |
|
|
309 | newreg->name = value; |
|
|
310 | } |
|
|
311 | else if (!strcmp (key, "parent")) |
|
|
312 | { |
|
|
313 | /* |
|
|
314 | * Note that this is in the initialisation code, so we don't actually |
|
|
315 | * assign the pointer to the parent yet, because it might not have been |
|
|
316 | * parsed. |
|
|
317 | */ |
|
|
318 | *end = 0; |
|
|
319 | newreg->parent_name = value; |
|
|
320 | } |
|
|
321 | else if (!strcmp (key, "longname")) |
|
|
322 | { |
|
|
323 | *end = 0; |
|
|
324 | newreg->longname = strdup (value); |
|
|
325 | } |
|
|
326 | else if (!strcmp (key, "jail")) |
|
|
327 | { |
|
|
328 | /* jail entries are of the form: /path/to/map x y */ |
|
|
329 | char path[MAX_BUF]; |
|
|
330 | int x, y; |
|
|
331 | |
|
|
332 | if (sscanf (value, "%[^ ] %d %d\n", path, &x, &y) != 3) |
|
|
333 | { |
|
|
334 | LOG (llevError, "region.c: malformated regions entry: jail %s\n", value); |
|
|
335 | continue; |
|
|
336 | } |
|
|
337 | newreg->jailmap = strdup (path); |
|
|
338 | newreg->jailx = x; |
|
|
339 | newreg->jaily = y; |
|
|
340 | } |
|
|
341 | else if (!strcmp (key, "msg")) |
|
|
342 | { |
|
|
343 | while (fgets (buf, HUGE_BUF - 1, fp) != NULL) |
|
|
344 | { |
|
|
345 | if (!strcmp (buf, "endmsg\n")) |
|
|
346 | break; |
|
|
347 | else |
|
|
348 | { |
|
|
349 | strcpy (msgbuf + msgpos, buf); |
|
|
350 | msgpos += strlen (buf); |
|
|
351 | } |
|
|
352 | } |
|
|
353 | /* |
|
|
354 | * There may be regions with empty messages (eg, msg/endmsg |
|
|
355 | * with nothing between). When maps are loaded, this is done |
|
|
356 | * so better do it here too... |
|
|
357 | */ |
|
|
358 | if (msgpos != 0) |
|
|
359 | newreg->msg = strdup (msgbuf); |
|
|
360 | |
|
|
361 | /* we have to reset msgpos, or the next region will store both msg blocks. */ |
|
|
362 | msgpos = 0; |
|
|
363 | } |
|
|
364 | else if (!strcmp (key, "fallback")) |
|
|
365 | { |
|
|
366 | *end = 0; |
|
|
367 | newreg->fallback = atoi (value); |
|
|
368 | } |
|
|
369 | else if (!strcmp (key, "end")) |
|
|
370 | { |
|
|
371 | /* Place this new region last on the list, if the list is empty put it first */ |
|
|
372 | for (reg = first_region; reg != NULL && reg->next != NULL; reg = reg->next); |
|
|
373 | |
|
|
374 | if (reg == NULL) |
|
|
375 | first_region = newreg; |
|
|
376 | else |
|
|
377 | reg->next = newreg; |
|
|
378 | newreg = NULL; |
|
|
379 | } |
|
|
380 | else if (!strcmp (key, "nomore")) |
|
|
381 | { |
|
|
382 | /* we have reached the end of the region specs.... */ |
|
|
383 | break; |
|
|
384 | } |
|
|
385 | else |
|
|
386 | { |
|
|
387 | /* we should never get here, if we have, then something is wrong */ |
|
|
388 | LOG (llevError, "Got unknown value in region file: %s %s\n", key, value); |
|
|
389 | } |
|
|
390 | } |
|
|
391 | if (!key || strcmp (key, "nomore")) |
|
|
392 | LOG (llevError, "Got premature eof on regions file!\n"); |
|
|
393 | } |
|
|
394 | |
|
|