|
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 00033 static void register_global_event(const char *plugin_name, int event_nr); 00034 static void unregister_global_event(const char *plugin_name, int event_nr); 00035 00037 struct plugin_hooklist hooklist = 00038 { 00039 query_name, 00040 re_cmp, 00041 present_in_ob, 00042 players_on_map, 00043 create_pathname, 00044 normalize_path, 00045 LOG, 00046 free_string_shared, 00047 add_string, 00048 remove_ob, 00049 fix_player, 00050 insert_ob_in_ob, 00051 new_info_map, 00052 new_info_map_except, 00053 spring_trap, 00054 cast_spell, 00055 update_ob_speed, 00056 command_rskill, 00057 become_follower, 00058 pick_up, 00059 get_map_from_coord, 00060 esrv_send_item, 00061 find_player, 00062 manual_apply, 00063 command_drop, 00064 transfer_ob, 00065 kill_object, 00066 do_learn_spell, 00067 do_forget_spell, 00068 look_up_spell_name, 00069 check_spell_known, 00070 esrv_send_inventory, 00071 get_archetype, 00072 ready_map_name, 00073 add_exp, 00074 determine_god, 00075 find_god, 00076 register_global_event, 00077 unregister_global_event, 00078 load_object_str, 00079 query_cost, 00080 query_money, 00081 pay_for_item, 00082 pay_for_amount, 00083 new_draw_info, 00084 communicate, 00085 object_create_clone, 00086 get_object, 00087 copy_object, 00088 enter_exit, 00089 play_sound_map, 00090 learn_skill, 00091 find_marked_object, 00092 cast_identify, 00093 lookup_skill_by_name, 00094 check_skill_known, 00095 find_archetype, 00096 arch_to_object, 00097 insert_ob_in_map, 00098 cost_string_from_value, 00099 bank_deposit, 00100 bank_withdraw, 00101 bank_get_balance, 00102 swap_apartments, 00103 player_exists, 00104 get_tod, 00105 object_get_value, 00106 object_set_value, 00107 drop, 00108 query_short_name, 00109 beacon_locate, 00110 strdup_local, 00111 adjust_player_name, 00112 find_party, 00113 add_party_member, 00114 remove_party_member, 00115 send_party_message, 00116 Write_String_To_Socket, 00117 dump_object, 00118 stringbuffer_new, 00119 stringbuffer_finish, 00120 cleanup_chat_string, 00121 cftimer_find_free_id, 00122 cftimer_create, 00123 cftimer_destroy, 00124 find_face, 00125 find_animation, 00126 play_sound_player_only, 00127 new_draw_info_format, 00128 was_destroyed, 00129 object_get_gender, 00130 change_abil, 00131 decrease_ob_nr, 00132 check_walk_off, 00133 wall, 00134 blocked, 00135 get_rangevector, 00136 get_rangevector_from_mapcoords, 00137 player_can_carry, 00138 cache_find, 00139 cache_add, 00140 cache_remove, 00141 cache_remove_by_flags, 00142 find_string, 00143 command_take, 00144 object_need_esrv_update, 00145 object_remove_esrv_update, 00146 esrv_update_item, 00147 execute_newserver_command, 00148 find_treasurelist, 00149 create_treasure, 00150 dump_object_rec, 00151 hit_player, 00152 move_ob, 00153 move_player, 00154 get_empty_map, 00155 set_map_darkness, 00156 find_free_spot, 00157 send_target_command, 00158 examine, 00159 push_button, 00160 00161 season_name, 00162 weekdays, 00163 month_name, 00164 periodsofday, 00165 spells, 00166 &shstr_cons, 00167 gender_noun, 00168 gender_subjective, 00169 gender_subjective_upper, 00170 gender_objective, 00171 gender_possessive, 00172 gender_reflexive, 00173 object_flag_names, 00174 freearr_x, 00175 freearr_y, 00176 &first_player, 00177 &new_faces, 00178 &nrofpixmaps, 00179 &animations, 00180 &num_animations, 00181 &first_archetype, 00182 &first_map, 00183 &first_party, 00184 &first_region, 00185 &logfile 00186 }; 00187 00189 static atrinik_plugin *plugins_list = NULL; 00190 00195 static atrinik_plugin *find_plugin(const char *id) 00196 { 00197 atrinik_plugin *plugin; 00198 00199 if (!plugins_list) 00200 { 00201 return NULL; 00202 } 00203 00204 for (plugin = plugins_list; plugin; plugin = plugin->next) 00205 { 00206 if (!strcmp(id, plugin->id)) 00207 { 00208 return plugin; 00209 } 00210 } 00211 00212 return NULL; 00213 } 00214 00219 static void register_global_event(const char *plugin_name, int event_nr) 00220 { 00221 atrinik_plugin *plugin = find_plugin(plugin_name); 00222 00223 if (!plugin) 00224 { 00225 LOG(llevBug, "register_global_event(): Could not find plugin %s.\n", plugin_name); 00226 return; 00227 } 00228 00229 LOG(llevDebug, "Plugin %s registered the event %d\n", plugin_name, event_nr); 00230 plugin->gevent[event_nr] = 1; 00231 } 00232 00237 static void unregister_global_event(const char *plugin_name, int event_nr) 00238 { 00239 atrinik_plugin *plugin = find_plugin(plugin_name); 00240 00241 if (!plugin) 00242 { 00243 LOG(llevBug, "unregister_global_event(): Could not find plugin %s.\n", plugin_name); 00244 return; 00245 } 00246 00247 plugin->gevent[event_nr] = 0; 00248 } 00249 00256 object *get_event_object(object *op, int event_nr) 00257 { 00258 object *tmp; 00259 00260 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 00261 { 00262 if (tmp->type == EVENT_OBJECT && tmp->sub_type == event_nr) 00263 { 00264 return tmp; 00265 } 00266 } 00267 00268 return tmp; 00269 } 00270 00275 CommArray_s *find_plugin_command(const char *cmd) 00276 { 00277 int i; 00278 atrinik_plugin *plugin; 00279 static CommArray_s rtn_cmd; 00280 00281 if (!plugins_list) 00282 { 00283 return NULL; 00284 } 00285 00286 for (plugin = plugins_list; plugin; plugin = plugin->next) 00287 { 00288 if (plugin->propfunc(&i, "command?", cmd, &rtn_cmd)) 00289 { 00290 return &rtn_cmd; 00291 } 00292 } 00293 00294 return NULL; 00295 } 00296 00300 void display_plugins_list(object *op) 00301 { 00302 char buf[MAX_BUF]; 00303 struct dirent *currentfile; 00304 DIR *plugdir; 00305 atrinik_plugin *plugin; 00306 00307 new_draw_info(0, COLOR_WHITE, op, "List of loaded plugins:"); 00308 new_draw_info(0, COLOR_WHITE, op, "-----------------------"); 00309 00310 for (plugin = plugins_list; plugin; plugin = plugin->next) 00311 { 00312 new_draw_info_format(0, COLOR_WHITE, op, "%s, %s", plugin->id, plugin->fullname); 00313 } 00314 00315 snprintf(buf, sizeof(buf), "%s/", PLUGINDIR); 00316 00317 /* Open the plugins directory */ 00318 if (!(plugdir = opendir(buf))) 00319 { 00320 return; 00321 } 00322 00323 new_draw_info(0, COLOR_WHITE, op, "\nList of loadable plugins:"); 00324 new_draw_info(0, COLOR_WHITE, op, "-----------------------"); 00325 00326 /* Go through the files in the directory */ 00327 while ((currentfile = readdir(plugdir))) 00328 { 00329 if (FILENAME_IS_PLUGIN(currentfile->d_name)) 00330 { 00331 new_draw_info(0, COLOR_WHITE, op, currentfile->d_name); 00332 } 00333 } 00334 00335 closedir(plugdir); 00336 } 00337 00342 void init_plugins() 00343 { 00344 struct dirent *currentfile; 00345 DIR *plugdir; 00346 char pluginfile[MAX_BUF]; 00347 00348 LOG(llevInfo, "Initializing plugins from '%s':\n", PLUGINDIR); 00349 00350 if (!(plugdir = opendir(PLUGINDIR))) 00351 { 00352 return; 00353 } 00354 00355 while ((currentfile = readdir(plugdir))) 00356 { 00357 if (FILENAME_IS_PLUGIN(currentfile->d_name)) 00358 { 00359 snprintf(pluginfile, sizeof(pluginfile), "%s/%s", PLUGINDIR, currentfile->d_name); 00360 LOG(llevInfo, "Loading plugin %s\n", currentfile->d_name); 00361 init_plugin(pluginfile); 00362 } 00363 } 00364 00365 closedir(plugdir); 00366 } 00367 00368 #ifdef WIN32 00369 00372 static const char *plugins_dlerror() 00373 { 00374 static char buf[MAX_BUF]; 00375 DWORD err = GetLastError(); 00376 char *p; 00377 00378 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, sizeof(buf), NULL) == 0) 00379 { 00380 snprintf(buf, sizeof(buf), "error %lu", err); 00381 } 00382 00383 p = strchr(buf, '\0'); 00384 00385 while (p > buf && (p[ - 1] == '\r' || p[ - 1] == '\n')) 00386 { 00387 p--; 00388 } 00389 00390 *p = '\0'; 00391 return buf; 00392 } 00393 #endif 00394 00398 void init_plugin(const char *pluginfile) 00399 { 00400 int i; 00401 LIBPTRTYPE ptr; 00402 f_plug_api eventfunc, propfunc; 00403 f_plug_init initfunc; 00404 f_plug_pinit pinitfunc, closefunc; 00405 atrinik_plugin *plugin; 00406 00407 ptr = plugins_dlopen(pluginfile); 00408 00409 if (!ptr) 00410 { 00411 LOG(llevBug, "Error while trying to load %s, returned: %s\n", pluginfile, plugins_dlerror()); 00412 return; 00413 } 00414 00415 initfunc = (f_plug_init) (plugins_dlsym(ptr, "initPlugin")); 00416 00417 if (!initfunc) 00418 { 00419 LOG(llevBug, "Error while requesting 'initPlugin' from %s: %s\n", pluginfile, plugins_dlerror()); 00420 plugins_dlclose(ptr); 00421 return; 00422 } 00423 00424 eventfunc = (f_plug_api) (plugins_dlsym(ptr, "triggerEvent")); 00425 00426 if (!eventfunc) 00427 { 00428 LOG(llevBug, "Error while requesting 'triggerEvent' from %s: %s\n", pluginfile, plugins_dlerror()); 00429 plugins_dlclose(ptr); 00430 return; 00431 } 00432 00433 pinitfunc = (f_plug_pinit) (plugins_dlsym(ptr, "postinitPlugin")); 00434 00435 if (!pinitfunc) 00436 { 00437 LOG(llevBug, "Error while requesting 'postinitPlugin' from %s: %s\n", pluginfile, plugins_dlerror()); 00438 plugins_dlclose(ptr); 00439 return; 00440 } 00441 00442 propfunc = (f_plug_api) (plugins_dlsym(ptr, "getPluginProperty")); 00443 00444 if (!propfunc) 00445 { 00446 LOG(llevBug, "Error while requesting 'getPluginProperty' from %s: %s\n", pluginfile, plugins_dlerror()); 00447 plugins_dlclose(ptr); 00448 return; 00449 } 00450 00451 closefunc = (f_plug_pinit) (plugins_dlsym(ptr, "closePlugin")); 00452 00453 if (!closefunc) 00454 { 00455 LOG(llevBug, "Error while requesting 'closePlugin' from %s: %s\n", pluginfile, plugins_dlerror()); 00456 plugins_dlclose(ptr); 00457 return; 00458 } 00459 00460 plugin = malloc(sizeof(atrinik_plugin)); 00461 00462 for (i = 0; i < GEVENT_NUM; i++) 00463 { 00464 plugin->gevent[i] = 0; 00465 } 00466 00467 plugin->eventfunc = eventfunc; 00468 plugin->propfunc = propfunc; 00469 plugin->libptr = ptr; 00470 plugin->next = NULL; 00471 plugin->closefunc = closefunc; 00472 00473 initfunc(&hooklist); 00474 propfunc(0, "Identification", plugin->id, sizeof(plugin->id)); 00475 propfunc(0, "FullName", plugin->fullname, sizeof(plugin->fullname)); 00476 LOG(llevDebug, "Plugin name: %s, known as %s\n", plugin->fullname, plugin->id); 00477 00478 if (!plugins_list) 00479 { 00480 plugins_list = plugin; 00481 } 00482 else 00483 { 00484 plugin->next = plugins_list; 00485 plugins_list = plugin; 00486 } 00487 00488 pinitfunc(); 00489 LOG(llevDebug, " [Done]\n"); 00490 } 00491 00495 void remove_plugin(const char *id) 00496 { 00497 atrinik_plugin *plugin, *prev = NULL; 00498 00499 if (!plugins_list) 00500 { 00501 return; 00502 } 00503 00504 for (plugin = plugins_list; plugin; prev = plugin, plugin = plugin->next) 00505 { 00506 if (!strcmp(plugin->id, id)) 00507 { 00508 if (!prev) 00509 { 00510 plugins_list = plugin->next; 00511 } 00512 else 00513 { 00514 prev->next = plugin->next; 00515 } 00516 00517 plugin->closefunc(); 00518 plugins_dlclose(plugin->libptr); 00519 free(plugin); 00520 break; 00521 } 00522 } 00523 } 00524 00527 void remove_plugins() 00528 { 00529 atrinik_plugin *plugin; 00530 00531 if (!plugins_list) 00532 { 00533 return; 00534 } 00535 00536 LOG(llevDebug, "Removing all plugins from memory.\n"); 00537 00538 for (plugin = plugins_list; plugin; ) 00539 { 00540 atrinik_plugin *next = plugin->next; 00541 00542 plugin->closefunc(); 00543 plugins_dlclose(plugin->libptr); 00544 free(plugin); 00545 plugin = next; 00546 } 00547 00548 plugins_list = NULL; 00549 } 00550 00554 void map_event_obj_init(object *ob) 00555 { 00556 map_event *tmp; 00557 00558 if (!ob->map) 00559 { 00560 LOG(llevBug, "Map event object not on map.\n"); 00561 return; 00562 } 00563 00564 tmp = malloc(sizeof(map_event)); 00565 tmp->plugin = NULL; 00566 tmp->event = ob; 00567 00568 tmp->next = ob->map->events; 00569 ob->map->events = tmp; 00570 } 00571 00575 void map_event_free(map_event *tmp) 00576 { 00577 free(tmp); 00578 } 00579 00583 void map_event_obj_deinit(object *ob) 00584 { 00585 map_event *tmp, *prev = NULL; 00586 00587 if (!ob->map) 00588 { 00589 return; 00590 } 00591 00592 for (tmp = ob->map->events; tmp; prev = tmp, tmp = tmp->next) 00593 { 00594 if (tmp->event == ob) 00595 { 00596 if (!prev) 00597 { 00598 ob->map->events = tmp->next; 00599 } 00600 else 00601 { 00602 prev->next = tmp->next; 00603 } 00604 00605 map_event_free(tmp); 00606 break; 00607 } 00608 } 00609 } 00610 00621 int trigger_map_event(int event_id, mapstruct *m, object *activator, object *other, object *other2, const char *text, int parm) 00622 { 00623 map_event *tmp; 00624 00625 if (!m->events) 00626 { 00627 return 0; 00628 } 00629 00630 for (tmp = m->events; tmp; tmp = tmp->next) 00631 { 00632 if (tmp->event->sub_type == event_id) 00633 { 00634 /* Load the event object's plugin as needed. */ 00635 if (!tmp->plugin) 00636 { 00637 tmp->plugin = find_plugin(tmp->event->name); 00638 00639 if (!tmp->plugin) 00640 { 00641 LOG(llevBug, "trigger_map_event(): Tried to trigger map event #%d, but could not find plugin '%s'.\n", event_id, tmp->event->name); 00642 return 0; 00643 } 00644 } 00645 00646 return *(int *) (tmp->plugin->eventfunc)(0, PLUGIN_EVENT_MAP, event_id, activator, tmp->event, other, other2, tmp->event->race, tmp->event->slaying, text, parm); 00647 } 00648 } 00649 00650 return 0; 00651 } 00652 00659 void trigger_global_event(int event_type, void *parm1, void *parm2) 00660 { 00661 atrinik_plugin *plugin; 00662 00663 if (!plugins_list) 00664 { 00665 return; 00666 } 00667 00668 for (plugin = plugins_list; plugin; plugin = plugin->next) 00669 { 00670 if (plugin->gevent[event_type]) 00671 { 00672 (plugin->eventfunc)(0, PLUGIN_EVENT_GLOBAL, event_type, parm1, parm2); 00673 } 00674 } 00675 } 00676 00690 int trigger_event(int event_type, object *const activator, object *const me, object *const other, const char *msg, int parm1, int parm2, int parm3, int flags) 00691 { 00692 object *event_obj; 00693 atrinik_plugin *plugin; 00694 00695 if (me == NULL || !(me->event_flags & EVENT_FLAG(event_type)) || !plugins_list) 00696 { 00697 return 0; 00698 } 00699 00700 if ((event_obj = get_event_object(me, event_type)) == NULL) 00701 { 00702 LOG(llevBug, "Object with event flag and no event object: %s\n", STRING_OBJ_NAME(me)); 00703 me->event_flags &= ~(1 << event_type); 00704 return 0; 00705 } 00706 00707 /* Ai event and we don't want this type of events. */ 00708 if (event_type == EVENT_AI && !(event_obj->path_attuned & EVENT_FLAG(parm1))) 00709 { 00710 return 0; 00711 } 00712 00713 if (event_obj->name && (plugin = find_plugin(event_obj->name))) 00714 { 00715 int returnvalue; 00716 #ifdef TIME_SCRIPTS 00717 struct timeval start, stop; 00718 uint64 start_u, stop_u; 00719 00720 gettimeofday(&start, NULL); 00721 #endif 00722 00723 returnvalue = *(int *) plugin->eventfunc(0, PLUGIN_EVENT_NORMAL, event_type, activator, me, other, event_obj, msg, parm1, parm2, parm3, flags, event_obj->race, event_obj->slaying); 00724 00725 #ifdef TIME_SCRIPTS 00726 gettimeofday(&stop, NULL); 00727 start_u = start.tv_sec * 1000000 + start.tv_usec; 00728 stop_u = stop.tv_sec * 1000000 + stop.tv_usec; 00729 00730 LOG(llevDebug, "Running time: %2.6f seconds\n", (stop_u - start_u) / 1000000.0); 00731 #endif 00732 return returnvalue; 00733 } 00734 else 00735 { 00736 LOG(llevBug, "event object with unknown plugin: %s, plugin %s\n", STRING_OBJ_NAME(me), STRING_OBJ_NAME(event_obj)); 00737 me->event_flags &= ~(1 << event_type); 00738 } 00739 00740 return 0; 00741 }
1.7.4