|
Atrinik Server 2.5
|
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 #include <loader.h> 00032 00034 #define TIME_ARCH_LOAD 0 00035 00037 static archetype *arch_table[ARCHTABLE]; 00039 int arch_cmp = 0; 00041 int arch_search = 0; 00043 int arch_init; 00044 00045 static void clear_archetable(); 00046 static void init_archetable(); 00047 static archetype *get_archetype_struct(); 00048 static void first_arch_pass(FILE *fp); 00049 static void second_arch_pass(FILE *fp_start); 00050 static void load_archetypes(); 00051 static unsigned long hasharch(const char *str, int tablesize); 00052 static void add_arch(archetype *at); 00053 00058 archetype *get_skill_archetype(int skillnr) 00059 { 00060 archetype *at; 00061 00062 for (at = first_archetype; at != NULL; at = at->next) 00063 { 00064 if (at->clone.type == SKILL && at->clone.stats.sp == skillnr) 00065 { 00066 return at; 00067 } 00068 } 00069 00070 return NULL; 00071 } 00072 00079 void init_archetypes() 00080 { 00081 /* Only do this once */ 00082 if (first_archetype != NULL) 00083 { 00084 return; 00085 } 00086 00087 arch_init = 1; 00088 load_archetypes(); 00089 arch_init = 0; 00090 empty_archetype = find_archetype("empty_archetype"); 00091 base_info_archetype = find_archetype("base_info"); 00092 wp_archetype = find_archetype("waypoint"); 00093 } 00094 00098 void arch_info(object *op) 00099 { 00100 char buf[MAX_BUF]; 00101 00102 snprintf(buf, sizeof(buf), "%d searches and %d strcmp()'s", arch_search, arch_cmp); 00103 new_draw_info(0, COLOR_WHITE, op, buf); 00104 } 00105 00108 static void clear_archetable() 00109 { 00110 memset((void *) arch_table, 0, ARCHTABLE * sizeof(archetype *)); 00111 } 00112 00116 static void init_archetable() 00117 { 00118 archetype *at; 00119 00120 LOG(llevDebug, "Setting up archetable..."); 00121 00122 for (at = first_archetype; at != NULL; at = (at->more == NULL) ? at->next : at->more) 00123 { 00124 add_arch(at); 00125 } 00126 00127 LOG(llevDebug, " done.\n"); 00128 } 00129 00132 void dump_all_archetypes() 00133 { 00134 archetype *at; 00135 artifactlist *al; 00136 artifact *art = NULL; 00137 StringBuffer *sb; 00138 char *diff; 00139 00140 for (at = first_archetype; at != NULL; at = (at->more == NULL) ? at->next : at->more) 00141 { 00142 sb = stringbuffer_new(); 00143 dump_object(&at->clone, sb); 00144 diff = stringbuffer_finish(sb); 00145 LOG(llevInfo, "%s\n", diff); 00146 free(diff); 00147 } 00148 00149 LOG(llevInfo, "Artifacts fake arch list:\n"); 00150 00151 for (al = first_artifactlist; al != NULL; al = al->next) 00152 { 00153 art = al->items; 00154 00155 do 00156 { 00157 sb = stringbuffer_new(); 00158 dump_object(&art->def_at.clone, sb); 00159 diff = stringbuffer_finish(sb); 00160 LOG(llevInfo, "%s\n", diff); 00161 free(diff); 00162 art = art->next; 00163 } 00164 while (art); 00165 } 00166 } 00167 00173 void free_all_archs() 00174 { 00175 archetype *at, *next; 00176 int i = 0; 00177 00178 for (at = first_archetype; at != NULL; at = next) 00179 { 00180 if (at->more) 00181 { 00182 next = at->more; 00183 } 00184 else 00185 { 00186 next = at->next; 00187 } 00188 00189 FREE_AND_CLEAR_HASH(at->name); 00190 FREE_AND_CLEAR_HASH(at->clone.name); 00191 FREE_AND_CLEAR_HASH(at->clone.title); 00192 FREE_AND_CLEAR_HASH(at->clone.race); 00193 FREE_AND_CLEAR_HASH(at->clone.slaying); 00194 FREE_AND_CLEAR_HASH(at->clone.msg); 00195 free_key_values(&at->clone); 00196 free(at); 00197 i++; 00198 } 00199 00200 LOG(llevDebug, "Freed %d archetypes\n", i); 00201 } 00202 00207 static archetype *get_archetype_struct() 00208 { 00209 archetype *new; 00210 00211 new = (archetype *) CALLOC(1, sizeof(archetype)); 00212 00213 if (new == NULL) 00214 { 00215 LOG(llevError, "get_archetype_struct(): Out of memory\n"); 00216 } 00217 00218 /* To initial state other also */ 00219 initialize_object(&new->clone); 00220 00221 return new; 00222 } 00223 00229 static void first_arch_pass(FILE *fp) 00230 { 00231 object *op; 00232 void *mybuffer; 00233 archetype *at,*prev = NULL, *last_more = NULL; 00234 int i, first = 2; 00235 00236 op = get_object(); 00237 op->arch = first_archetype = at = get_archetype_struct(); 00238 mybuffer = create_loader_buffer(fp); 00239 00240 while ((i = load_object(fp, op, mybuffer, first, MAP_STYLE))) 00241 { 00242 first = 0; 00243 00244 copy_object(op, &at->clone, 1); 00245 00246 /* Now we have the right speed_left value for out object. 00247 * copy_object() now will track down negative speed values, to 00248 * alter speed_left to guarantee a random & sensible start value. */ 00249 if (!op->layer && !QUERY_FLAG(op, FLAG_SYS_OBJECT)) 00250 { 00251 LOG(llevDebug, "Archetype %s has layer 0 without being sys_object!\n", STRING_OBJ_ARCH_NAME(op)); 00252 } 00253 00254 if (op->layer && QUERY_FLAG(op, FLAG_SYS_OBJECT)) 00255 { 00256 LOG(llevDebug, "Archetype %s has layer %d (!= 0) and is sys_object!\n", STRING_OBJ_ARCH_NAME(op), op->layer); 00257 } 00258 00259 switch (i) 00260 { 00261 /* A new archetype, just link it with the previous */ 00262 case LL_NORMAL: 00263 if (last_more != NULL) 00264 { 00265 last_more->next = at; 00266 } 00267 00268 if (prev != NULL) 00269 { 00270 prev->next = at; 00271 } 00272 00273 prev = last_more = at; 00274 00275 if (!op->type) 00276 { 00277 LOG(llevDebug, "Archetype %s has no type!\n", STRING_OBJ_ARCH_NAME(op)); 00278 } 00279 00280 break; 00281 00282 /* Another part of the previous archetype, link it correctly */ 00283 case LL_MORE: 00284 at->head = prev; 00285 at->clone.head = &prev->clone; 00286 00287 if (last_more != NULL) 00288 { 00289 last_more->more = at; 00290 last_more->clone.more = &at->clone; 00291 } 00292 00293 last_more = at; 00294 00295 break; 00296 } 00297 00298 at = get_archetype_struct(); 00299 initialize_object(op); 00300 op->arch = at; 00301 } 00302 00303 delete_loader_buffer(mybuffer); 00304 /* Make sure our temp object is gc:ed */ 00305 mark_object_removed(op); 00306 free(at); 00307 } 00308 00313 static void second_arch_pass(FILE *fp_start) 00314 { 00315 FILE *fp = fp_start; 00316 int comp; 00317 char filename[MAX_BUF], buf[MAX_BUF], *variable = buf, *argument, *cp; 00318 archetype *at = NULL, *other; 00319 object *inv; 00320 00321 while (fgets(buf, MAX_BUF, fp) != NULL) 00322 { 00323 if (*buf == '#') 00324 { 00325 continue; 00326 } 00327 00328 if ((argument = strchr(buf, ' ')) != NULL) 00329 { 00330 *argument = '\0', argument++; 00331 cp = argument + strlen(argument) - 1; 00332 00333 while (isspace(*cp)) 00334 { 00335 *cp = '\0'; 00336 cp--; 00337 } 00338 } 00339 00340 if (!strcmp("Object", variable)) 00341 { 00342 if ((at = find_archetype(argument)) == NULL) 00343 { 00344 LOG(llevBug, "Failed to find arch %s\n", STRING_SAFE(argument)); 00345 } 00346 } 00347 else if (!strcmp("other_arch", variable)) 00348 { 00349 if (at != NULL && at->clone.other_arch == NULL) 00350 { 00351 if ((other = find_archetype(argument)) == NULL) 00352 { 00353 LOG(llevBug, "Failed to find other_arch %s\n", STRING_SAFE(argument)); 00354 } 00355 else if (at != NULL) 00356 { 00357 at->clone.other_arch = other; 00358 } 00359 } 00360 } 00361 else if (!strcmp("randomitems", variable)) 00362 { 00363 if (at != NULL) 00364 { 00365 treasurelist *tl = find_treasurelist(argument); 00366 00367 if (tl == NULL) 00368 { 00369 LOG(llevBug, "Failed to link treasure to arch. (arch: %s ->%s\n", STRING_OBJ_NAME(&at->clone), STRING_SAFE(argument)); 00370 } 00371 else 00372 { 00373 at->clone.randomitems = tl; 00374 } 00375 } 00376 } 00377 else if (!strcmp("arch", variable)) 00378 { 00379 inv = get_archetype(argument); 00380 load_object(fp, inv, NULL, LO_LINEMODE, 0); 00381 00382 if (at) 00383 { 00384 insert_ob_in_ob(inv, &at->clone); 00385 } 00386 else 00387 { 00388 LOG(llevError, "Got an arch %s not inside an Object.\n", argument); 00389 } 00390 } 00391 } 00392 00393 /* Now re-parse the artifacts file too! */ 00394 snprintf(filename, sizeof(filename), "%s/artifacts", settings.datadir); 00395 00396 if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) 00397 { 00398 LOG(llevError, "Can't open %s.\n", filename); 00399 return; 00400 } 00401 00402 while (fgets(buf, MAX_BUF, fp) != NULL) 00403 { 00404 if (*buf == '#') 00405 { 00406 continue; 00407 } 00408 00409 if ((argument = strchr(buf, ' ')) != NULL) 00410 { 00411 *argument = '\0', argument++; 00412 cp = argument + strlen(argument) - 1; 00413 00414 while (isspace(*cp)) 00415 { 00416 *cp = '\0'; 00417 cp--; 00418 } 00419 } 00420 00421 /* Now we get our artifact. if we hit "def_arch", we first copy 00422 * from it other_arch and treasure list to our artifact. Then we 00423 * search the object for other_arch and randomitems - perhaps we 00424 * override them here. */ 00425 if (!strcmp("artifact", variable)) 00426 { 00427 if ((at = find_archetype(argument)) == NULL) 00428 { 00429 LOG(llevBug, "Second artifacts pass: Failed to find artifact %s\n", STRING_SAFE(argument)); 00430 } 00431 } 00432 else if (!strcmp("def_arch", variable)) 00433 { 00434 if ((other = find_archetype(argument)) == NULL) 00435 { 00436 LOG(llevBug, "Second artifacts pass: Failed to find def_arch %s from artifact %s\n", STRING_SAFE(argument), STRING_ARCH_NAME(at)); 00437 } 00438 00439 /* now copy from real arch the stuff from above to our "fake" arches */ 00440 at->clone.other_arch = other->clone.other_arch; 00441 at->clone.randomitems = other->clone.randomitems; 00442 } 00443 else if (!strcmp("other_arch", variable)) 00444 { 00445 if ((other = find_archetype(argument)) == NULL) 00446 { 00447 LOG(llevBug, "Second artifacts pass: Failed to find other_arch %s\n", STRING_SAFE(argument)); 00448 } 00449 else if (at != NULL) 00450 { 00451 at->clone.other_arch = other; 00452 } 00453 } 00454 else if (!strcmp("randomitems", variable)) 00455 { 00456 treasurelist *tl = find_treasurelist(argument); 00457 00458 if (tl == NULL) 00459 { 00460 LOG(llevBug, "Second artifacts pass: Failed to link treasure to arch. (arch: %s ->%s)\n", STRING_OBJ_NAME(&at->clone), STRING_SAFE(argument)); 00461 } 00462 else if (at != NULL) 00463 { 00464 at->clone.randomitems = tl; 00465 } 00466 } 00467 } 00468 00469 close_and_delete(fp, comp); 00470 } 00471 00479 static void load_archetypes() 00480 { 00481 FILE *fp; 00482 char filename[MAX_BUF]; 00483 int comp; 00484 #if TIME_ARCH_LOAD 00485 struct timeval tv1, tv2; 00486 #endif 00487 00488 snprintf(filename, sizeof(filename), "%s/%s", settings.datadir, settings.archetypes); 00489 LOG(llevDebug, "Reading archetypes from %s...\n", filename); 00490 00491 if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) 00492 { 00493 LOG(llevError, "Can't open archetype file.\n"); 00494 return; 00495 } 00496 00497 clear_archetable(); 00498 LOG(llevDebug, "arch-pass 1...\n"); 00499 00500 #if TIME_ARCH_LOAD 00501 GETTIMEOFDAY(&tv1); 00502 #endif 00503 00504 first_arch_pass(fp); 00505 00506 #if TIME_ARCH_LOAD 00507 int sec, usec; 00508 GETTIMEOFDAY(&tv2); 00509 sec = tv2.tv_sec - tv1.tv_sec; 00510 usec = tv2.tv_usec - tv1.tv_usec; 00511 00512 if (usec < 0) 00513 { 00514 usec += 1000000; 00515 sec--; 00516 } 00517 00518 LOG(llevDebug, "Load took %d.%06d seconds\n", sec, usec); 00519 #endif 00520 00521 LOG(llevDebug, " done.\n"); 00522 init_archetable(); 00523 00524 /* Do a close and reopen instead of a rewind - necessary in case the 00525 * file has been compressed. */ 00526 close_and_delete(fp, comp); 00527 fp = open_and_uncompress(filename, 0, &comp); 00528 00529 /* If not called before, reads all artifacts from file */ 00530 init_artifacts(); 00531 LOG(llevDebug, " loading treasure...\n"); 00532 load_treasures(); 00533 LOG(llevDebug, " done\n arch-pass 2...\n"); 00534 second_arch_pass(fp); 00535 LOG(llevDebug, " done.\n"); 00536 00537 close_and_delete(fp, comp); 00538 LOG(llevDebug, "Reading archetypes done.\n"); 00539 } 00540 00546 object *arch_to_object(archetype *at) 00547 { 00548 object *op; 00549 00550 if (at == NULL) 00551 { 00552 LOG(llevBug, "arch_to_object(): Archetype at is NULL.\n"); 00553 return NULL; 00554 } 00555 00556 op = get_object(); 00557 copy_object_with_inv(&at->clone, op); 00558 op->arch = at; 00559 00560 return op; 00561 } 00562 00572 object *create_singularity(const char *name) 00573 { 00574 object *op; 00575 char buf[MAX_BUF]; 00576 00577 snprintf(buf, sizeof(buf), "singularity (%s)", name); 00578 op = get_object(); 00579 FREE_AND_COPY_HASH(op->name, buf); 00580 SET_FLAG(op, FLAG_NO_PICK); 00581 00582 return op; 00583 } 00584 00591 object *get_archetype(const char *name) 00592 { 00593 archetype *at = find_archetype(name); 00594 00595 if (at == NULL) 00596 { 00597 return create_singularity(name); 00598 } 00599 00600 return arch_to_object(at); 00601 } 00602 00608 static unsigned long hasharch(const char *str, int tablesize) 00609 { 00610 unsigned long hash = 0; 00611 int i = 0; 00612 const char *p; 00613 00614 for (p = str; i < MAXSTRING && *p; p++, i++) 00615 { 00616 hash += *p; 00617 hash += hash << 10; 00618 hash ^= hash >> 6; 00619 } 00620 00621 hash += hash << 3; 00622 hash ^= hash >> 11; 00623 hash += hash << 15; 00624 00625 return hash % tablesize; 00626 } 00627 00631 archetype *find_archetype(const char *name) 00632 { 00633 archetype *at; 00634 unsigned long idx; 00635 00636 if (name == NULL) 00637 { 00638 return NULL; 00639 } 00640 00641 idx = hasharch(name, ARCHTABLE); 00642 arch_search++; 00643 00644 for (; ;) 00645 { 00646 at = arch_table[idx]; 00647 00648 /* Not in archetype list - let's try the artifacts file */ 00649 if (at == NULL) 00650 { 00651 return find_artifact_archtype(name); 00652 } 00653 00654 arch_cmp++; 00655 00656 if (!strcmp(at->name, name)) 00657 { 00658 return at; 00659 } 00660 00661 if (++idx >= ARCHTABLE) 00662 { 00663 idx = 0; 00664 } 00665 } 00666 } 00667 00670 static void add_arch(archetype *at) 00671 { 00672 unsigned long idx = hasharch(at->name, ARCHTABLE), org_idx = idx; 00673 00674 for (; ;) 00675 { 00676 if (arch_table[idx] && !strcmp(arch_table[idx]->name, at->name)) 00677 { 00678 LOG(llevError, "add_arch(): Double use of arch name %s.\n", STRING_ARCH_NAME(at)); 00679 } 00680 00681 if (arch_table[idx] == NULL) 00682 { 00683 arch_table[idx] = at; 00684 return; 00685 } 00686 00687 if (++idx == ARCHTABLE) 00688 { 00689 idx = 0; 00690 } 00691 00692 if (idx == org_idx) 00693 { 00694 LOG(llevError, "add_arch(): Archtable too small.\n"); 00695 } 00696 } 00697 } 00698
1.7.4