int inter_parse_frommap(int fd) { int cmd; int len = 0; cmd = RFIFOW(fd,0); // inter鯖管轄かを調べる if(cmd < 0x3000 || cmd >= 0x3000 + ARRAYLENGTH(inter_recv_packet_length) || inter_recv_packet_length[cmd - 0x3000] == 0) return 0; // パケット長を調べる if((len = inter_check_length(fd, inter_recv_packet_length[cmd - 0x3000])) == 0) return 2; switch(cmd) { case 0x3000: mapif_parse_broadcast(fd); break; case 0x3001: mapif_parse_WisRequest(fd); break; case 0x3002: mapif_parse_WisReply(fd); break; case 0x3003: mapif_parse_WisToGM(fd); break; case 0x3004: mapif_parse_Registry(fd); break; case 0x3005: mapif_parse_RegistryRequest(fd); break; case 0x3006: mapif_parse_NameChangeRequest(fd); break; default: if( inter_party_parse_frommap(fd) || inter_guild_parse_frommap(fd) || inter_storage_parse_frommap(fd) || inter_pet_parse_frommap(fd) || inter_homunculus_parse_frommap(fd) || inter_mercenary_parse_frommap(fd) || inter_mail_parse_frommap(fd) || inter_auction_parse_frommap(fd) || inter_quest_parse_frommap(fd) ) break; else return 0; } RFIFOSKIP(fd, len); return 1; }
void read_homunculus_expdb(void) { int i; char *filename[]={ DBPATH"exp_homun.txt", DBIMPORT"/exp_homun.txt" }; memset(hexptbl,0,sizeof(hexptbl)); for(i=0; i<ARRAYLENGTH(filename); i++){ FILE *fp; char line[1024]; int j=0; sprintf(line, "%s/%s", db_path, filename[i]); fp=fopen(line,"r"); if(fp == NULL){ if(i != 0) continue; if(i==0) ShowError("Can't read %s\n",line); return; } while(fgets(line, sizeof(line), fp) && j < MAX_LEVEL) { if(line[0] == '/' && line[1] == '/') continue; hexptbl[j] = strtoul(line, NULL, 10); if (!hexptbl[j++]) break; } if (hexptbl[MAX_LEVEL - 1]) // Last permitted level have to be 0! { ShowWarning("read_hexptbl: Reached max level in %s [%d]. Remaining lines were not read.\n ",filename,MAX_LEVEL); hexptbl[MAX_LEVEL - 1] = 0; } fclose(fp); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' levels in '"CL_WHITE"%s/%s"CL_RESET"'.\n", j, db_path, filename[i]); } }
/// Initializes a chatroom object (common functionality for both pc and npc chatrooms). /// Returns a chatroom object on success, or NULL on failure. static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl) { struct chat_data* cd; nullpo_retr(NULL, bl); cd = (struct chat_data *) aMalloc(sizeof(struct chat_data)); safestrncpy(cd->title, title, sizeof(cd->title)); safestrncpy(cd->pass, pass, sizeof(cd->pass)); cd->pub = pub; cd->users = 0; cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); cd->trigger = trigger; cd->zeny = zeny; cd->minLvl = minLvl; cd->maxLvl = maxLvl; memset(cd->usersd, 0, sizeof(cd->usersd)); cd->owner = bl; safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event)); cd->bl.id = map_get_new_object_id(); cd->bl.m = bl->m; cd->bl.x = bl->x; cd->bl.y = bl->y; cd->bl.type = BL_CHAT; cd->bl.next = cd->bl.prev = NULL; if( cd->bl.id == 0 ) { aFree(cd); cd = NULL; } map_addiddb(&cd->bl); if( bl->type != BL_NPC ) cd->kick_list = idb_alloc(DB_OPT_BASE); return cd; }
/* Handler for KMSG_CRED_NEW_CREDS */ khm_int32 handle_kmsg_cred_new_creds(khui_new_creds * nc) { wchar_t wshortdesc[KHUI_MAXCCH_SHORT_DESC]; size_t cb = 0; struct nc_dialog_data * d; /* This is a minimal handler that just adds a dialog pane to the new credentials window to handle new credentials acquisition for this credentials type. */ /* TODO: add additional initialization etc. as needed */ d = malloc(sizeof(*d)); ZeroMemory(d, sizeof(*d)); d->nct.type = credtype_id; d->nct.ordinal = -1; LoadString(hResModule, IDS_CT_SHORT_DESC, wshortdesc, ARRAYLENGTH(wshortdesc)); StringCbLength(wshortdesc, sizeof(wshortdesc), &cb); #ifdef DEBUG assert(cb > 0); #endif cb += sizeof(wchar_t); d->nct.name = malloc(cb); StringCbCopy(d->nct.name, cb, wshortdesc); d->nct.h_module = hResModule; d->nct.dlg_proc = nc_dlg_proc; d->nct.dlg_template = MAKEINTRESOURCE(IDD_NEW_CREDS); khui_cw_add_type(nc, &d->nct); khui_cw_add_selector(nc, idsel_factory, NULL); return KHM_ERROR_SUCCESS; }
/// Initializes a chatroom object (common functionality for both pc and npc chatrooms). /// Returns a chatroom object on success, or NULL on failure. struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl) { struct chat_data* cd; nullpo_retr(NULL, bl); /* Given the overhead and the numerous instances (npc allocated or otherwise) wouldn't it be beneficial to have it use ERS? [Ind] */ cd = (struct chat_data *) aMalloc(sizeof(struct chat_data)); safestrncpy(cd->title, title, sizeof(cd->title)); safestrncpy(cd->pass, pass, sizeof(cd->pass)); cd->pub = pub; cd->users = 0; cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); cd->trigger = trigger; cd->zeny = zeny; cd->minLvl = minLvl; cd->maxLvl = maxLvl; memset(cd->usersd, 0, sizeof(cd->usersd)); cd->owner = bl; safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event)); cd->bl.id = map->get_new_object_id(); cd->bl.m = bl->m; cd->bl.x = bl->x; cd->bl.y = bl->y; cd->bl.type = BL_CHAT; cd->bl.next = cd->bl.prev = NULL; if( cd->bl.id == 0 ) { aFree(cd); return NULL; } map->addiddb(&cd->bl); if( bl->type != BL_NPC ) cd->kick_list = idb_alloc(DB_OPT_BASE); return cd; }
void k4_update_display(k4_dlg_data * d, BOOL update_methods) { CheckDlgButton(d->hwnd, IDC_NCK4_OBTAIN, (d->k4_enabled)?BST_CHECKED: BST_UNCHECKED); if (d->k4_enabled) { EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), TRUE); EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), TRUE); EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), TRUE); } else { EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), FALSE); EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), FALSE); EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), FALSE); } #ifdef DEBUG assert(d->method >= 0 && d->method < ARRAYLENGTH(method_to_id)); #endif CheckRadioButton(d->hwnd, IDC_NCK4_AUTO, IDC_NCK4_PWD, method_to_id[d->method]); khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled); }
void console_load_defaults(void) { struct { char *name; CParseFunc func; char *connect; struct CParseEntry *self; } default_list[] = { CP_DEF(help), CP_DEF_C(server), CP_DEF_S(ers_report,server), CP_DEF_S(mem_report,server), CP_DEF_S(malloc_usage,server), CP_DEF_S(exit,server), }; unsigned int i, len = ARRAYLENGTH(default_list); struct CParseEntry *cmd; RECREATE(console->cmds,struct CParseEntry *, len); for(i = 0; i < len; i++) { CREATE(cmd, struct CParseEntry, 1); safestrncpy(cmd->cmd, default_list[i].name, CP_CMD_LENGTH); if( default_list[i].func ) cmd->u.func = default_list[i].func; else cmd->u.next = NULL; cmd->next_count = 0; console->cmd_count++; console->cmds[i] = cmd; default_list[i].self = cmd; if( !default_list[i].connect ) { RECREATE(console->cmd_list,struct CParseEntry *, ++console->cmd_list_count); console->cmd_list[console->cmd_list_count - 1] = cmd; } }
void HttpRequest::ReportStatus(kherr_severity severity, const wchar_t * message, const wchar_t * long_desc, ...) { HttpRequestStatusListener * listener; va_list args; DWORD gle; va_start(args, long_desc); gle = GetLastError(); listener = (HttpRequestStatusListener *) m_listener; if (listener && !m_muted) { wchar_t ld[2048]; if (long_desc) StringCchVPrintf(ld, ARRAYLENGTH(ld), long_desc, args); listener->HttpRequestStatus(severity, message, ((long_desc)? ld: NULL)); } }
void HttpRequest::FetchImageFromURL() { HANDLE hFile = INVALID_HANDLE_VALUE; do { URL_COMPONENTS uc; wchar_t domain[MAX_PATH]; memset(&uc, 0, sizeof(uc)); uc.dwStructSize = sizeof(uc); uc.lpszHostName = domain; uc.dwHostNameLength = ARRAYLENGTH(domain); uc.lpszUrlPath = NULL; uc.dwUrlPathLength = 1; if (!WinHttpCrackUrl(m_target.c_str(), 0, 0, &uc)) break; FetchResource(domain, uc.lpszUrlPath, image_mimetypes); } while(FALSE); }
void load_message_file_source(void) { #define ARRAYLENGTH(A) ( sizeof(A)/sizeof((A)[0]) ) config_setting_t *main_group = NULL; config_t group_ext; int index=0; if (libconfig->read_file(&group_ext, bra_config.lang_file)) return; memset(lang_s, 0, sizeof(LANG)); if((main_group = config_lookup(&group_ext, "Source"))) { int i, h, k = 0, groups_count = libconfig->setting_length(main_group); config_setting_t *group_ele; config_setting_t *groups; for(i = 0; i < groups_count; ++i) { group_ele = libconfig->setting_get_elem(main_group, i); while(k < ARRAYLENGTH(Source) && (groups = libconfig->setting_get_member(group_ele, Source[k]))) { int group_count = config_setting_length(groups); for(h = 0; h < group_count; h++) { config_setting_t *group_e = libconfig->setting_get_elem(groups, h); copy_to_list((char *)config_setting_name(group_e), (char *)config_setting_get_string_elem(groups, h), index); index++; } k++; } } } ShowConf("Leitura de '"CL_WHITE"%d"CL_RESET"' mensagens em '"CL_WHITE"%s"CL_RESET"'.\n", index, bra_config.lang_file); }
/*========================================== * Return item data from item name. (lookup) *------------------------------------------*/ struct item_data* itemdb_searchname(const char *str) { struct item_data* item; struct item_data* item2 = NULL; int i; for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) { item = itemdb_array[i]; if( item == NULL ) continue; //Absolute priority to Aegis code name. if( strcasecmp(item->name,str) == 0 ) return item; //Second priority to Client displayed name. if( strcasecmp(item->jname,str) == 0 ) item2 = item; } item = NULL; itemdb_other->foreach(itemdb_other,itemdb_searchname_sub,str,&item,&item2); return item ? item : item2; }
/*========================================== * Loads (and creates if not found) an item from the db. *------------------------------------------*/ struct item_data *itemdb_load (int nameid) { struct item_data *id; if (nameid >= 0 && nameid < ARRAYLENGTH (itemdb_array)) { id = itemdb_array[nameid]; if (id == NULL || id == &dummy_item) id = itemdb_array[nameid] = create_item_data (nameid); return id; } id = (struct item_data *) idb_get (itemdb_other, nameid); if (id == NULL || id == &dummy_item) { id = create_item_data (nameid); idb_put (itemdb_other, nameid, id); } return id; }
void k4_handle_wmnc_notify(k4_dlg_data * d, WPARAM wParam, LPARAM lParam) { switch(HIWORD(wParam)) { case WMNC_IDENTITY_CHANGE: k4_read_identity_data(d); k4_update_display(d, TRUE); break; case WMNC_CREDTEXT_LINK: { wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD]; wchar_t * wids; khui_htwnd_link * l; l = (khui_htwnd_link *) lParam; StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len); wids = wcschr(wid, L':'); if (!wids) break; else wids++; if (!wcscmp(wids, L"Enable")) { d->k4_enabled = TRUE; k4_update_display(d, TRUE); khui_cw_enable_type(d->nc, credtype_id_krb4, TRUE); } } break; } }
/*========================================== * アイテムデータベースの読み込み *------------------------------------------*/ static int itemdb_readdb(void) { const char* filename[] = { #if REMODE "re/item_db.txt", #else "pre-re/item_db.txt", #endif "item_db2.txt" }; int fi; for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) { uint32 lines = 0, count = 0; char line[1024]; char path[256]; FILE* fp; sprintf(path, "%s/%s", db_path, filename[fi]); fp = fopen(path, "r"); if( fp == NULL ) { ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path); continue; } // process rows one by one while(fgets(line, sizeof(line), fp)) { char *str[32], *p; int i; lines++; if(line[0] == '/' && line[1] == '/') continue; memset(str, 0, sizeof(str)); p = line; while( ISSPACE(*p) ) ++p; if( *p == '\0' ) continue;// empty line for( i = 0; i < 19; ++i ) { str[i] = p; p = strchr(p,','); if( p == NULL ) break;// comma not found *p = '\0'; ++p; } if( p == NULL ) { ShowError("itemdb_readdb: Insufficient columns in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } // Script if( *p != '{' ) { ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } str[19] = p; p = strstr(p+1,"},"); if( p == NULL ) { ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } p[1] = '\0'; p += 2; // OnEquip_Script if( *p != '{' ) { ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } str[20] = p; p = strstr(p+1,"},"); if( p == NULL ) { ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } p[1] = '\0'; p += 2; // OnUnequip_Script (last column) if( *p != '{' ) { ShowError("itemdb_readdb: Invalid format (OnUnequip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } str[21] = p; if (!itemdb_parse_dbrow(str, path, lines, 0)) continue; count++; } fclose(fp); ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename[fi]); } return 0; }
/** * Loads group configuration from config file into memory. * @private */ static void read_config(void) { config_setting_t *groups = NULL; const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name int group_count = 0; if (conf_read_file(&pc_group_config, config_filename)) return; groups = config_lookup(&pc_group_config, "groups"); if (groups != NULL) { GroupSettings *group_settings = NULL; DBIterator *iter = NULL; int i, loop = 0; group_count = config_setting_length(groups); for (i = 0; i < group_count; ++i) { int id = 0, level = 0; const char *groupname = NULL; int log_commands = 0; config_setting_t *group = config_setting_get_elem(groups, i); if (!config_setting_lookup_int(group, "id", &id)) { ShowConfigWarning(group, "pc_groups:read_config: \"groups\" list member #%d has undefined id, removing...", i); config_setting_remove_elem(groups, i); --i; --group_count; continue; } if (id2group(id) != NULL) { ShowConfigWarning(group, "pc_groups:read_config: duplicate group id %d, removing...", i); config_setting_remove_elem(groups, i); --i; --group_count; continue; } config_setting_lookup_int(group, "level", &level); config_setting_lookup_bool(group, "log_commands", &log_commands); if (!config_setting_lookup_string(group, "name", &groupname)) { char temp[20]; config_setting_t *name = NULL; snprintf(temp, sizeof(temp), "Group %d", id); if ((name = config_setting_add(group, "name", CONFIG_TYPE_STRING)) == NULL || !config_setting_set_string(name, temp)) { ShowError("pc_groups:read_config: failed to set missing group name, id=%d, skipping... (%s:%d)\n", id, config_setting_source_file(group), config_setting_source_line(group)); continue; } config_setting_lookup_string(group, "name", &groupname); // Retrieve the pointer } if (name2group(groupname) != NULL) { ShowConfigWarning(group, "pc_groups:read_config: duplicate group name %s, removing...", groupname); config_setting_remove_elem(groups, i); --i; --group_count; continue; } CREATE(group_settings, GroupSettings, 1); group_settings->id = id; group_settings->level = level; group_settings->name = groupname; group_settings->log_commands = (bool)log_commands; group_settings->inherit = config_setting_get_member(group, "inherit"); group_settings->commands = config_setting_get_member(group, "commands"); group_settings->permissions = config_setting_get_member(group, "permissions"); group_settings->inheritance_done = false; group_settings->root = group; group_settings->group_pos = i; strdb_put(pc_groupname_db, groupname, group_settings); idb_put(pc_group_db, id, group_settings); } group_count = config_setting_length(groups); // Save number of groups // Check if all commands and permissions exist iter = db_iterator(pc_group_db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions; int count = 0, j; // Make sure there is "commands" group if (commands == NULL) commands = group_settings->commands = config_setting_add(group_settings->root, "commands", CONFIG_TYPE_GROUP); count = config_setting_length(commands); for (j = 0; j < count; ++j) { config_setting_t *command = config_setting_get_elem(commands, j); const char *name = config_setting_name(command); if (!atcommand_exists(name)) { ShowConfigWarning(command, "pc_groups:read_config: non-existent command name '%s', removing...", name); config_setting_remove(commands, name); --j; --count; } } // Make sure there is "permissions" group if (permissions == NULL) permissions = group_settings->permissions = config_setting_add(group_settings->root, "permissions", CONFIG_TYPE_GROUP); count = config_setting_length(permissions); for(j = 0; j < count; ++j) { config_setting_t *permission = config_setting_get_elem(permissions, j); const char *name = config_setting_name(permission); int p; ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), p, strcmp(pc_g_permission_name[p].name, name) == 0); if (p == ARRAYLENGTH(pc_g_permission_name)) { ShowConfigWarning(permission, "pc_groups:read_config: non-existent permission name '%s', removing...", name); config_setting_remove(permissions, name); --p; --count; } } } dbi_destroy(iter); // Apply inheritance i = 0; // counter for processed groups while (i < group_count) { iter = db_iterator(pc_group_db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { config_setting_t *inherit = NULL, *commands = group_settings->commands, *permissions = group_settings->permissions; int j, inherit_count = 0, done = 0; if (group_settings->inheritance_done) // group already processed continue; if ((inherit = group_settings->inherit) == NULL || (inherit_count = config_setting_length(inherit)) <= 0) { // this group does not inherit from others ++i; group_settings->inheritance_done = true; continue; } for (j = 0; j < inherit_count; ++j) { GroupSettings *inherited_group = NULL; const char *groupname = config_setting_get_string_elem(inherit, j); if (groupname == NULL) { ShowConfigWarning(inherit, "pc_groups:read_config: \"inherit\" array member #%d is not a name, removing...", j); config_setting_remove_elem(inherit,j); continue; } if ((inherited_group = name2group(groupname)) == NULL) { ShowConfigWarning(inherit, "pc_groups:read_config: non-existent group name \"%s\", removing...", groupname); config_setting_remove_elem(inherit,j); continue; } if (!inherited_group->inheritance_done) continue; // we need to do that group first // Copy settings (commands/permissions) that are not defined yet if (inherited_group->commands != NULL) { int l = 0, commands_count = config_setting_length(inherited_group->commands); for (l = 0; l < commands_count; ++l) config_setting_copy(commands, config_setting_get_elem(inherited_group->commands, l)); } if (inherited_group->permissions != NULL) { int l = 0, permissions_count = config_setting_length(inherited_group->permissions); for (l = 0; l < permissions_count; ++l) config_setting_copy(permissions, config_setting_get_elem(inherited_group->permissions, l)); } ++done; // copied commands and permissions from one of inherited groups } if (done == inherit_count) { // copied commands from all of inherited groups ++i; group_settings->inheritance_done = true; // we're done with this group } } dbi_destroy(iter); if (++loop > group_count) { ShowWarning("pc_groups:read_config: Could not process inheritance rules, check your config '%s' for cycles...\n", config_filename); break; } } // while(i < group_count) // Pack permissions into GroupSettings.e_permissions for faster checking iter = db_iterator(pc_group_db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { config_setting_t *permissions = group_settings->permissions; int c, count = config_setting_length(permissions); for (c = 0; c < count; ++c) { config_setting_t *perm = config_setting_get_elem(permissions, c); const char *name = config_setting_name(perm); int val = config_setting_get_bool(perm); int j; if (val == 0) // does not have this permission continue; ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0); group_settings->e_permissions |= pc_g_permission_name[j].permission; } } dbi_destroy(iter); } ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename); if( ( pc_group_max = group_count ) ) { DBIterator *iter = db_iterator(pc_group_db); GroupSettings *group_settings = NULL; int* group_ids = aMalloc( pc_group_max * sizeof(int) ); int i = 0; for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { group_ids[i++] = group_settings->id; } atcommand_db_load_groups(group_ids); aFree(group_ids); dbi_destroy(iter); } }
/** * Gives bonus to Mercenary * @param md Mercenary **/ void mercenary_killbonus(struct mercenary_data *md) { const enum sc_type scs[] = { SC_MERC_FLEEUP, SC_MERC_ATKUP, SC_MERC_HPUP, SC_MERC_SPUP, SC_MERC_HITUP }; uint8 index = rnd() % ARRAYLENGTH(scs); sc_start(&md->bl,&md->bl, scs[index], 100, rnd() % 5, 600000); }
/// parse input string into the provided account data structure static bool mmo_auth_fromstr(struct mmo_account* a, char* str, unsigned int version) { char* fields[32]; int count; char* regs; int i, n; // zero out the destination first memset(a, 0x00, sizeof(struct mmo_account)); // extract tab-separated columns from line count = sv_split(str, strlen(str), 0, '\t', fields, ARRAYLENGTH(fields), (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF)); if( version == ACCOUNT_TXT_DB_VERSION && count == 13 ) { a->account_id = strtol(fields[1], NULL, 10); safestrncpy(a->userid, fields[2], sizeof(a->userid)); safestrncpy(a->pass, fields[3], sizeof(a->pass)); a->sex = fields[4][0]; safestrncpy(a->email, fields[5], sizeof(a->email)); a->level = strtoul(fields[6], NULL, 10); a->state = strtoul(fields[7], NULL, 10); a->unban_time = strtol(fields[8], NULL, 10); a->expiration_time = strtol(fields[9], NULL, 10); a->logincount = strtoul(fields[10], NULL, 10); safestrncpy(a->lastlogin, fields[11], sizeof(a->lastlogin)); safestrncpy(a->last_ip, fields[12], sizeof(a->last_ip)); regs = fields[13]; } else if( version == 0 && count == 14 ) { a->account_id = strtol(fields[1], NULL, 10); safestrncpy(a->userid, fields[2], sizeof(a->userid)); safestrncpy(a->pass, fields[3], sizeof(a->pass)); safestrncpy(a->lastlogin, fields[4], sizeof(a->lastlogin)); a->sex = fields[5][0]; a->logincount = strtoul(fields[6], NULL, 10); a->state = strtoul(fields[7], NULL, 10); safestrncpy(a->email, fields[8], sizeof(a->email)); //safestrncpy(a->error_message, fields[9], sizeof(a->error_message)); a->expiration_time = strtol(fields[10], NULL, 10); safestrncpy(a->last_ip, fields[11], sizeof(a->last_ip)); //safestrncpy(a->memo, fields[12], sizeof(a->memo)); a->unban_time = strtol(fields[13], NULL, 10); regs = fields[14]; } else if( version == 0 && count == 13 ) { a->account_id = strtol(fields[1], NULL, 10); safestrncpy(a->userid, fields[2], sizeof(a->userid)); safestrncpy(a->pass, fields[3], sizeof(a->pass)); safestrncpy(a->lastlogin, fields[4], sizeof(a->lastlogin)); a->sex = fields[5][0]; a->logincount = strtoul(fields[6], NULL, 10); a->state = strtoul(fields[7], NULL, 10); safestrncpy(a->email, fields[8], sizeof(a->email)); //safestrncpy(a->error_message, fields[9], sizeof(a->error_message)); a->expiration_time = strtol(fields[10], NULL, 10); safestrncpy(a->last_ip, fields[11], sizeof(a->last_ip)); //safestrncpy(a->memo, fields[12], sizeof(a->memo)); regs = fields[13]; } else if( version == 0 && count == 8 ) { a->account_id = strtol(fields[1], NULL, 10); safestrncpy(a->userid, fields[2], sizeof(a->userid)); safestrncpy(a->pass, fields[3], sizeof(a->pass)); safestrncpy(a->lastlogin, fields[4], sizeof(a->lastlogin)); a->sex = fields[5][0]; a->logincount = strtoul(fields[6], NULL, 10); a->state = strtoul(fields[7], NULL, 10); regs = fields[8]; } else {// unmatched row return false; } // extract account regs // {reg name<COMMA>reg value<SPACE>}* n = 0; for( i = 0; i < ACCOUNT_REG2_NUM; ++i ) { char key[32]; char value[256]; regs += n; if (sscanf(regs, "%31[^\t,],%255[^\t ] %n", key, value, &n) != 2) { // We must check if a str is void. If it's, we can continue to read other REG2. // Account line will have something like: str2,9 ,9 str3,1 (here, ,9 is not good) if (regs[0] == ',' && sscanf(regs, ",%[^\t ] %n", value, &n) == 1) { i--; continue; } else break; } safestrncpy(a->account_reg2[i].str, key, 32); safestrncpy(a->account_reg2[i].value, value, 256); } a->account_reg2_num = i; return true; }
/* there needs to be at least one language that is supported. Here we declare that to be US English, and make it the default. */ LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), MYPLUGIN_DLLBASEW L"_en_us.dll", /* this is the name of the DLL. We paste a trailer to basename of the DLL. This DLL should reside in the same directory as the plugin DLL. */ KMM_MLOC_FLAG_DEFAULT) }; int n_locales = ARRAYLENGTH(locales); /******************************************************************* init_module ***************************************************************** This is the entry point for the module. Each module can provide multiple plugins and each plugin will need a separate entry point. Generally, the module entry point will set up localized resources and register the plugins. */ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) { khm_int32 rv = KHM_ERROR_SUCCESS; kmm_plugin_reg pi;
/*========================================== * path search (x0,y0)->(x1,y1) * wpd: path info will be written here * flag: &1 = easy path search only * cell: type of obstruction to check for *------------------------------------------*/ bool path_search (struct walkpath_data *wpd, int m, int x0, int y0, int x1, int y1, int flag, cell_chk cell) { int heap[MAX_HEAP + 1]; struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH]; register int i, j, len, x, y, dx, dy; int rp, xs, ys; struct map_data *md; struct walkpath_data s_wpd; if (wpd == NULL) wpd = &s_wpd; // use dummy output variable if (!map[m].cell) return false; md = &map[m]; #ifdef CELL_NOSTACK //Do not check starting cell as that would get you stuck. if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys) #else if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| map_getcellp(md,x0,y0,cell)*/) #endif return false; if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || map_getcellp (md, x1, y1, cell)) return false; // calculate (sgn(x1-x0), sgn(y1-y0)) dx = ( (dx = x1 - x0)) ? ( (dx < 0) ? -1 : 1) : 0; dy = ( (dy = y1 - y0)) ? ( (dy < 0) ? -1 : 1) : 0; // try finding direct path to target x = x0; y = y0; i = 0; while (i < ARRAYLENGTH (wpd->path)) { wpd->path[i] = walk_choices[-dy + 1][dx + 1]; i++; x += dx; y += dy; if (x == x1) dx = 0; if (y == y1) dy = 0; if (dx == 0 && dy == 0) break; // success if (map_getcellp (md, x, y, cell)) break; // obstacle = failure } if (x == x1 && y == y1) { //easy path successful. wpd->path_len = i; wpd->path_pos = 0; return true; } if (flag & 1) return false; memset (tp, 0, sizeof (tp)); i = calc_index (x0, y0); tp[i].x = x0; tp[i].y = y0; tp[i].dist = 0; tp[i].before = 0; tp[i].cost = calc_cost (&tp[i], x1, y1); tp[i].flag = 0; heap[0] = 0; push_heap_path (heap, tp, calc_index (x0, y0)); xs = md->xs - 1; // あらかじめ1減算しておく ys = md->ys - 1; for (;;) { int e = 0, f = 0, dist, cost, dc[4] = {0, 0, 0, 0}; if (heap[0] == 0) return false; rp = pop_heap_path (heap, tp); x = tp[rp].x; y = tp[rp].y; dist = tp[rp].dist + 10; cost = tp[rp].cost; if (x == x1 && y == y1) break; // dc[0] : y++ の時のコスト増分 // dc[1] : x-- の時のコスト増分 // dc[2] : y-- の時のコスト増分 // dc[3] : x++ の時のコスト増分 if (y < ys && !map_getcellp (md, x , y + 1, cell)) { f |= 1; dc[0] = (y >= y1 ? 20 : 0); e += add_path (heap, tp, x , y + 1, dist, rp, cost + dc[0]); // (x, y+1) } if (x > 0 && !map_getcellp (md, x - 1, y , cell)) { f |= 2; dc[1] = (x <= x1 ? 20 : 0); e += add_path (heap, tp, x - 1, y , dist, rp, cost + dc[1]); // (x-1, y ) } if (y > 0 && !map_getcellp (md, x , y - 1, cell)) { f |= 4; dc[2] = (y <= y1 ? 20 : 0); e += add_path (heap, tp, x , y - 1, dist, rp, cost + dc[2]); // (x , y-1) } if (x < xs && !map_getcellp (md, x + 1, y , cell)) { f |= 8; dc[3] = (x >= x1 ? 20 : 0); e += add_path (heap, tp, x + 1, y , dist, rp, cost + dc[3]); // (x+1, y ) } if ( (f & (2 + 1)) == (2 + 1) && !map_getcellp (md, x - 1, y + 1, cell)) e += add_path (heap, tp, x - 1, y + 1, dist + 4, rp, cost + dc[1] + dc[0] - 6); // (x-1, y+1) if ( (f & (2 + 4)) == (2 + 4) && !map_getcellp (md, x - 1, y - 1, cell)) e += add_path (heap, tp, x - 1, y - 1, dist + 4, rp, cost + dc[1] + dc[2] - 6); // (x-1, y-1) if ( (f & (8 + 4)) == (8 + 4) && !map_getcellp (md, x + 1, y - 1, cell)) e += add_path (heap, tp, x + 1, y - 1, dist + 4, rp, cost + dc[3] + dc[2] - 6); // (x+1, y-1) if ( (f & (8 + 1)) == (8 + 1) && !map_getcellp (md, x + 1, y + 1, cell)) e += add_path (heap, tp, x + 1, y + 1, dist + 4, rp, cost + dc[3] + dc[0] - 6); // (x+1, y+1) tp[rp].flag = 1; if (e || heap[0] >= MAX_HEAP - 5) return false; } if (! (x == x1 && y == y1)) // will never happen... return false; for (len = 0, i = rp; len < 100 && i != calc_index (x0, y0); i = tp[i].before, len++); if (len == 100 || len >= sizeof (wpd->path)) return false; wpd->path_len = len; wpd->path_pos = 0; for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--) { int dx = tp[i].x - tp[tp[i].before].x; int dy = tp[i].y - tp[tp[i].before].y; int dir; if (dx == 0) { dir = (dy > 0 ? 0 : 4); } else if (dx > 0) { dir = (dy == 0 ? 6 : (dy < 0 ? 5 : 7)); } else { dir = (dy == 0 ? 2 : (dy > 0 ? 1 : 3)); } wpd->path[j] = dir; } return true; }
static INT_PTR on_browse(HWND hwnd) { OPENFILENAME ofn; wchar_t path[MAX_PATH] = L""; wchar_t filter[128]; wchar_t title[64]; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hwnd; ofn.hInstance = hResModule; ofn.lpstrFilter = filter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 1; ofn.lpstrFile = path; ofn.nMaxFile = MAX_PATH; ofn.lpstrTitle = title; ofn.Flags = OFN_DONTADDTORECENT | OFN_NOREADONLYRETURN; ofn.lpstrDefExt = L"keystore"; GetDlgItemText(hwnd, IDC_PATH, path, ARRAYLENGTH(path)); LoadString(hResModule, IDS_NC_BROW_TITLE, title, ARRAYLENGTH(title)); LoadString(hResModule, IDS_NC_BROW_FILTER, filter, ARRAYLENGTH(filter)); { wchar_t * c = filter; for (; *c; c++) { if (*c == L'%') *c = L'\0'; } } if (GetOpenFileName(&ofn)) { keystore_t * ks = NULL; wchar_t fpath[MAX_PATH+5]; SetDlgItemText(hwnd, IDC_PATH, path); if (PathFileExists(path)) { StringCbCopy(fpath, sizeof(fpath), L"FILE:"); StringCbCat(fpath, sizeof(fpath), path); ks = create_keystore_from_location(fpath, NULL); if (ks) { wchar_t buf[KCDB_MAXCCH_SHORT_DESC]; khm_size cb; cb = sizeof(buf); if (KHM_SUCCEEDED(ks_keystore_get_string(ks, KCDB_RES_DISPLAYNAME, buf, &cb))) { SetDlgItemText(hwnd, IDC_NAME, buf); } if (KHM_SUCCEEDED(ks_keystore_get_string(ks, KCDB_RES_DESCRIPTION, buf, &cb))) { SetDlgItemText(hwnd, IDC_DESCRIPTION, buf); } ks_keystore_release(ks); } } } return TRUE; }
/*========================================== * *------------------------------------------*/ int chrif_parse(int fd) { int packet_len, cmd; // only process data from the char-server if (fd != char_fd) { ShowDebug("chrif_parse: Disconnecting invalid session #%d (is not the char-server)\n", fd); do_close(fd); return 0; } if (session[fd]->flag.eof) { if (chrif_connected == 1) chrif_disconnect(fd); do_close(fd); return 0; } while (RFIFOREST(fd) >= 2) { cmd = RFIFOW(fd,0); if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { int r = intif_parse(fd); // intifに渡す if (r == 1) continue; // intifで処理した if (r == 2) return 0; // intifで処理したが、データが足りない ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd); set_eof(fd); return 0; } packet_len = packet_len_table[cmd-0x2af8]; if (packet_len == -1) { // dynamic-length packet, second WORD holds the length if (RFIFOREST(fd) < 4) return 0; packet_len = RFIFOW(fd,2); } if ((int)RFIFOREST(fd) < packet_len) return 0; //ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd); switch(cmd) { case 0x2af9: chrif_connectack(fd); break; case 0x2afb: chrif_sendmapack(fd); break; case 0x2afd: chrif_authok(fd); break; case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break; case 0x2b03: clif_charselectok(RFIFOL(fd,2)); break; case 0x2b04: chrif_recvmap(fd); break; case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; case 0x2b07: clif_updatemaxid(RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; case 0x2b0b: chrif_changedgm(fd); break; case 0x2b0d: chrif_changedsex(fd); break; case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break; case 0x2b12: chrif_divorce(RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x2b13: chrif_accountdeletion(fd); break; case 0x2b14: chrif_accountban(fd); break; case 0x2b15: chrif_recvgmaccounts(fd); break; case 0x2b1b: chrif_recvfamelist(fd); break; case 0x2b1d: chrif_load_scdata(fd); break; case 0x2b1e: chrif_update_ip(fd); break; case 0x2b1f: chrif_disconnectplayer(fd); break; case 0x2b20: chrif_removemap(fd); break; case 0x2b21: chrif_save_ack(fd); break; case 0x2b22: chrif_updatefamelist_ack(fd); break; case 0x2b24: chrif_keepalive_ack(fd); break; default: ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); set_eof(fd); return 0; } if (fd == char_fd) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex] RFIFOSKIP(fd, packet_len); } return 0; }
/** * loginchrif destructor * dealloc..., function called at exit of the login-serv */ void do_final_loginchrif(void){ int i; for( i = 0; i < ARRAYLENGTH(ch_server); ++i ) logchrif_server_destroy(i); }
/* Dialog procedure for IDD_IDSEL runs in UI thread */ static INT_PTR CALLBACK idspec_dlg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_INITDIALOG: { struct idsel_dlg_data * d; d = PMALLOC(sizeof(*d)); ZeroMemory(d, sizeof(*d)); d->magic = IDSEL_DLG_DATA_MAGIC; d->identity = NULL; #pragma warning(push) #pragma warning(disable: 4244) SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); #pragma warning(pop) /* TODO: Initialize controls etc. */ } CheckRadioButton(hwnd, IDC_REGISTRY, IDC_FILE, IDC_REGISTRY); EnableWindow(GetDlgItem(hwnd, IDC_PATH), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), FALSE); SendDlgItemMessage(hwnd, IDC_NAME, EM_SETLIMITTEXT, KCDB_MAXCCH_NAME, 0); SendDlgItemMessage(hwnd, IDC_DESCRIPTION, EM_SETLIMITTEXT, KCDB_MAXCCH_SHORT_DESC, 0); SendDlgItemMessage(hwnd, IDC_PATH, EM_SETLIMITTEXT, MAX_PATH, 0); { wchar_t cuebanner[KCDB_MAXCCH_NAME]; LoadString(hResModule, IDS_CUE_NAME, cuebanner, ARRAYLENGTH(cuebanner)); SendDlgItemMessage(hwnd, IDC_NAME, EM_SETCUEBANNER, 0, (LPARAM)cuebanner); LoadString(hResModule, IDS_CUE_DESC, cuebanner, ARRAYLENGTH(cuebanner)); SendDlgItemMessage(hwnd, IDC_DESCRIPTION, EM_SETCUEBANNER, 0, (LPARAM)cuebanner); } /* We return FALSE here because this is an embedded modeless dialog and we don't want to steal focus from the container. */ return FALSE; case WM_DESTROY: { struct idsel_dlg_data * d; d = (struct idsel_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); #ifdef DEBUG assert(d != NULL); assert(d->magic == IDSEL_DLG_DATA_MAGIC); #endif if (d && d->magic == IDSEL_DLG_DATA_MAGIC) { if (d->identity) { kcdb_identity_release(d->identity); d->identity = NULL; } d->magic = 0; PFREE(d); } #pragma warning(push) #pragma warning(disable: 4244) SetWindowLongPtr(hwnd, DWLP_USER, 0); #pragma warning(pop) } return TRUE; case WM_COMMAND: { switch (wParam) { case MAKEWPARAM(IDC_REGISTRY, BN_CLICKED): EnableWindow(GetDlgItem(hwnd, IDC_PATH), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), FALSE); return TRUE; case MAKEWPARAM(IDC_FILE, BN_CLICKED): EnableWindow(GetDlgItem(hwnd, IDC_PATH), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), TRUE); return TRUE; case MAKEWPARAM(IDC_BROWSE, BN_CLICKED): return on_browse(hwnd); } } break; case KHUI_WM_NC_NOTIFY: { struct idsel_dlg_data * d; khm_handle * ph; d = (struct idsel_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); switch (HIWORD(wParam)) { case WMNC_IDSEL_GET_IDENT: ph = (khm_handle *) lParam; on_get_ident(hwnd, d, ph); break; } } return TRUE; } return FALSE; }
/** * Signal handler * This function attempts to properly close the server when an interrupt signal is received. * current signal catch : SIGTERM, SIGINT */ void do_shutdown_loginchrif(void){ int id; for( id = 0; id < ARRAYLENGTH(ch_server); ++id ) logchrif_server_reset(id); }
/*========================================== * *------------------------------------------*/ int chrif_parse(int fd) { int packet_len, cmd; // only process data from the char-server if ( fd != char_fd ) { ShowDebug("chrif_parse: Disconnecting invalid session #%d (is not the char-server)\n", fd); do_close(fd); return 0; } if ( session[fd]->flag.eof ) { do_close(fd); char_fd = -1; chrif_on_disconnect(); return 0; } else if ( session[fd]->flag.ping ) {/* we've reached stall time */ if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */ set_eof(fd); return 0; } else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */ chrif_keepalive(fd); session[fd]->flag.ping = 2; } } while ( RFIFOREST(fd) >= 2 ) { cmd = RFIFOW(fd,0); if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { int r = intif_parse(fd); // Passed on to the intif if (r == 1) continue; // Treated in intif if (r == 2) return 0; // Didn't have enough data (len==-1) ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd); set_eof(fd); return 0; } if ( ( packet_len = packet_len_table[cmd-0x2af8] ) == -1) { // dynamic-length packet, second WORD holds the length if (RFIFOREST(fd) < 4) return 0; packet_len = RFIFOW(fd,2); } if ((int)RFIFOREST(fd) < packet_len) return 0; //ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd); switch(cmd) { case 0x2af9: chrif_connectack(fd); break; case 0x2afb: chrif_sendmapack(fd); break; case 0x2afd: chrif_authok(fd); break; case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break; case 0x2b03: clif->charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break; case 0x2b04: chrif_recvmap(fd); break; case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; case 0x2b0a: socket_datasync(fd, false); break; case 0x2b0d: chrif_changedsex(fd); break; case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break; case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x2b14: chrif_accountban(fd); break; case 0x2b1b: chrif_recvfamelist(fd); break; case 0x2b1d: chrif_load_scdata(fd); break; case 0x2b1e: chrif_update_ip(fd); break; case 0x2b1f: chrif_disconnectplayer(fd); break; case 0x2b20: chrif_removemap(fd); break; case 0x2b21: chrif_save_ack(fd); break; case 0x2b22: chrif_updatefamelist_ack(fd); break; case 0x2b24: chrif_keepalive_ack(fd); break; case 0x2b25: chrif_deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break; case 0x2b27: chrif_authfail(fd); break; default: ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); set_eof(fd); return 0; } if ( fd == char_fd ) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex] RFIFOSKIP(fd, packet_len); } return 0; }
/* process KMSG_SYSTEM messages */ khm_int32 KHMAPI afs_msg_system(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam) { khm_int32 rv = KHM_ERROR_UNKNOWN; switch(msg_subtype) { case KMSG_SYSTEM_INIT: /* If we are building against an older SDK, we should try to load newer APIs if it's available at run-time. */ #if KH_VERSION_API < 7 do { khm_version libver; khm_ui_4 apiver; khm_get_lib_version(&libver, &apiver); if (apiver < 7) break; hm_netidmgr = LoadLibrary(NIMDLLNAME); if (hm_netidmgr == NULL) break; pkhui_action_lock = (void (KHMAPI *)(void)) GetProcAddress(hm_netidmgr, API_khui_action_lock); pkhui_action_unlock = (void (KHMAPI *)(void)) GetProcAddress(hm_netidmgr, API_khui_action_unlock); pkhui_refresh_actions = (void (KHMAPI *)(void)) GetProcAddress(hm_netidmgr, API_khui_refresh_actions); pkhui_request_UI_callback = (khm_int32 (KHMAPI *)(khm_ui_callback, void *)) GetProcAddress(hm_netidmgr, API_khui_request_UI_callback); } while (FALSE); #endif /* Add the icon now. On NIM v2.x, doing so after tokens were reported may result in a deadlock as we try to switch to the UI thread and the UI thread is blocked on a resource request to this plug-in. */ afs_icon_set_state(AFSICON_SERVICE_STOPPED, NULL); /* Perform critical registrations and data structure initalization */ { kcdb_credtype ct; wchar_t buf[KCDB_MAXCCH_LONG_DESC]; size_t cbsize; kcdb_attrib att; khm_handle csp_afscred = NULL; khm_int32 disable_afscreds = FALSE; ZeroMemory(&ct, sizeof(ct)); /* first of all, register the AFS token credential type */ ct.id = KCDB_CREDTYPE_AUTO; ct.name = AFS_CREDTYPE_NAME; if(LoadString(hResModule, IDS_AFS_SHORT_DESC, buf, ARRAYLENGTH(buf)) != 0) { StringCbLength(buf, sizeof(buf), &cbsize); cbsize += sizeof(wchar_t); ct.short_desc = PMALLOC(cbsize); StringCbCopy(ct.short_desc, cbsize, buf); } else ct.short_desc = NULL; if(LoadString(hResModule, IDS_AFS_LONG_DESC, buf, ARRAYLENGTH(buf)) != 0) { StringCbLength(buf, sizeof(buf), &cbsize); cbsize += sizeof(wchar_t); ct.long_desc = PMALLOC(cbsize); StringCbCopy(ct.long_desc, cbsize, buf); } else ct.long_desc = NULL; ct.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_AFSTOKEN), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); kmq_create_subscription(afs_plugin_cb, &afs_sub); ct.sub = afs_sub; kcdb_credtype_register(&ct, &afs_credtype_id); /* register the attribute types */ { kcdb_type type; ZeroMemory(&type, sizeof(type)); type.comp = afs_type_principal_comp; type.dup = afs_type_principal_dup; type.isValid = afs_type_principal_isValid; type.toString = afs_type_principal_toString; type.name = AFS_TYPENAME_PRINCIPAL; type.id = KCDB_TYPE_INVALID; type.cb_max = sizeof(struct ktc_principal); type.cb_min = sizeof(struct ktc_principal); type.flags = KCDB_TYPE_FLAG_CB_FIXED; if(KHM_FAILED(kcdb_type_register(&type, &afs_type_principal))) goto _exit_init; } { kcdb_type type; kcdb_type *ti32 = NULL; kcdb_type_get_info(KCDB_TYPE_INT32, &ti32); ZeroMemory(&type, sizeof(type)); type.comp = ti32->comp; type.dup = ti32->dup; type.isValid = ti32->isValid; type.toString = afs_type_method_toString; type.name = AFS_TYPENAME_METHOD; type.id = KCDB_TYPE_INVALID; type.cb_max = sizeof(khm_int32); type.cb_min = sizeof(khm_int32); type.flags = KCDB_TYPE_FLAG_CB_FIXED; if(KHM_FAILED(kcdb_type_register(&type, &afs_type_method))) { kcdb_type_release_info(ti32); goto _exit_init; } kcdb_type_release_info(ti32); } /* now register the attributes */ { wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; ZeroMemory(&att, sizeof(att)); att.type = KCDB_TYPE_STRING; att.name = AFS_ATTRNAME_CELL; LoadString(hResModule, IDS_ATTR_CELL_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); att.short_desc = short_desc; att.long_desc = NULL; att.id = KCDB_ATTR_INVALID; att.flags = KCDB_ATTR_FLAG_TRANSIENT; if(KHM_FAILED(rv = kcdb_attrib_register(&att, &afs_attr_cell))) goto _exit_init; } { wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; ZeroMemory(&att, sizeof(att)); att.type = KCDB_TYPE_STRING; att.name = AFS_ATTRNAME_REALM; LoadString(hResModule, IDS_ATTR_REALM_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); att.short_desc = short_desc; att.long_desc = NULL; att.id = KCDB_ATTR_INVALID; att.flags = KCDB_ATTR_FLAG_TRANSIENT; if(KHM_FAILED(rv = kcdb_attrib_register(&att, &afs_attr_realm))) goto _exit_init; } { wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; ZeroMemory(&att, sizeof(att)); att.type = afs_type_method; att.name = AFS_ATTRNAME_METHOD; LoadString(hResModule, IDS_ATTR_METHOD_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); att.short_desc = short_desc; att.long_desc = NULL; att.id = KCDB_ATTR_INVALID; att.flags = KCDB_ATTR_FLAG_TRANSIENT; if(KHM_FAILED(rv = kcdb_attrib_register(&att, &afs_attr_method))) goto _exit_init; } { wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; ZeroMemory(&att, sizeof(att)); att.type = afs_type_principal; att.name = AFS_ATTRNAME_CLIENT_PRINC; LoadString(hResModule, IDS_ATTR_CLIENT_PRINC_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); att.short_desc = short_desc; att.long_desc = NULL; att.id = KCDB_ATTR_INVALID; att.flags = KCDB_ATTR_FLAG_TRANSIENT; if(KHM_FAILED(rv = kcdb_attrib_register(&att, &afs_attr_client_princ))) goto _exit_init; } { wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; ZeroMemory(&att, sizeof(att)); att.type = afs_type_principal; att.name = AFS_ATTRNAME_SERVER_PRINC; LoadString(hResModule, IDS_ATTR_SERVER_PRINC_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); att.short_desc = short_desc; att.long_desc = NULL; att.id = KCDB_ATTR_INVALID; att.flags = KCDB_ATTR_FLAG_TRANSIENT; if(KHM_FAILED(rv = kcdb_attrib_register(&att, &afs_attr_server_princ))) goto _exit_init; } /* afs_credset is our stock credentials set that we use for all our credset needs (instead of creating a new one every time) */ if(KHM_FAILED(rv = kcdb_credset_create(&afs_credset))) goto _exit_init; if(KHM_FAILED(rv = kcdb_credtype_get_id(KRB5_CREDTYPE_NAME, &krb5_credtype_id))) goto _exit_init; /* register the configuration nodes */ { khui_config_node node_ident; khui_config_node_reg reg; wchar_t wshort_desc[KHUI_MAXCCH_SHORT_DESC]; wchar_t wlong_desc[KHUI_MAXCCH_LONG_DESC]; if (KHM_FAILED(rv = khui_cfg_open(NULL, L"KhmIdentities", &node_ident))) goto _exit_init; ZeroMemory(®, sizeof(reg)); reg.name = AFS_CONFIG_NODE_MAIN; reg.short_desc = wshort_desc; reg.long_desc = wlong_desc; reg.h_module = hResModule; reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_AFS); reg.dlg_proc = afs_cfg_main_proc; reg.flags = 0; LoadString(hResModule, IDS_CFG_MAIN_LONG, wlong_desc, ARRAYLENGTH(wlong_desc)); LoadString(hResModule, IDS_CFG_MAIN_SHORT, wshort_desc, ARRAYLENGTH(wshort_desc)); khui_cfg_register(NULL, ®); ZeroMemory(®, sizeof(reg)); reg.name = AFS_CONFIG_NODE_IDS; reg.short_desc = wshort_desc; reg.long_desc = wshort_desc; reg.h_module = hResModule; reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB); reg.dlg_proc = afs_cfg_ids_proc; reg.flags = KHUI_CNFLAG_SUBPANEL; LoadString(hResModule, IDS_CFG_IDS_TAB, wshort_desc, ARRAYLENGTH(wshort_desc)); khui_cfg_register(node_ident, ®); ZeroMemory(®, sizeof(reg)); reg.name = AFS_CONFIG_NODE_ID; reg.short_desc = wshort_desc; reg.long_desc = wshort_desc; reg.h_module = hResModule; reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB); reg.dlg_proc = afs_cfg_id_proc; reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL; LoadString(hResModule, IDS_CFG_ID_TAB, wshort_desc, ARRAYLENGTH(wshort_desc)); khui_cfg_register(node_ident, ®); } /* and register the AFS message type */ rv = kmq_register_type(AFS_MSG_TYPENAME, &afs_msg_type_id); if (KHM_SUCCEEDED(rv)) kmq_subscribe(afs_msg_type_id, afs_plugin_cb); /* if the configuration is set to disable afscreds.exe, then we look for the shortcut and remove it if found. */ if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME, 0, &csp_afscred))) { wchar_t wpath[MAX_PATH]; khc_read_int32(csp_afscred, L"Disableafscreds", &disable_afscreds); if (disable_afscreds && afs_cfg_get_afscreds_shortcut(wpath)) { DeleteFile(wpath); } khc_close_space(csp_afscred); } /* try to register the "AFS Help" menu item, if possible */ { khm_handle h_sub = NULL; wchar_t short_desc[KHUI_MAXCCH_SHORT_DESC]; wchar_t long_desc[KHUI_MAXCCH_LONG_DESC]; #if KH_VERSION_API < 7 if (pkhui_action_lock == NULL || pkhui_action_unlock == NULL || pkhui_refresh_actions == NULL || pkhui_request_UI_callback == NULL) goto no_custom_help; #endif kmq_create_subscription(afs_plugin_cb, &h_sub); LoadString(hResModule, IDS_ACTION_AFS_HELP, short_desc, ARRAYLENGTH(short_desc)); LoadString(hResModule, IDS_ACTION_AFS_HELP_TT, long_desc, ARRAYLENGTH(long_desc)); action_id_afs_help = khui_action_create(NULL, short_desc, long_desc, NULL, KHUI_ACTIONTYPE_TRIGGER, h_sub); if (action_id_afs_help != 0) { khm_size s; khm_size i; khui_menu_def * help_menu; khm_boolean refresh = FALSE; khui_action_lock(); help_menu = khui_find_menu(KHUI_MENU_HELP); if (help_menu) { s = khui_menu_get_size(help_menu); for (i=0; i < s; i++) { khui_action_ref * aref; aref = khui_menu_get_action(help_menu, i); if (aref && !(aref->flags & KHUI_ACTIONREF_PACTION) && aref->action == KHUI_ACTION_HELP_INDEX) { khui_menu_insert_action(help_menu, i + 1, action_id_afs_help, 0); refresh = TRUE; break; } } } khui_action_unlock(); if (refresh) khui_refresh_actions(); } #if KH_VERSION_API < 7 no_custom_help: ; #endif } _exit_init: if(ct.short_desc) PFREE(ct.short_desc); if(ct.long_desc) PFREE(ct.long_desc); } /* now that the critical stuff is done, we move on to the non-critical stuff */ if(KHM_SUCCEEDED(rv)) { initialized = TRUE; /* obtain existing tokens */ afs_list_tokens(); } /* define this so that if there are no TGT's, we don't deadlock trying to open a new creds dialog from within the new creds dialog. */ SetEnvironmentVariable(L"KERBEROSLOGIN_NEVER_PROMPT", L"1"); break; /* end of KMSG_SYSTEM_INIT */ case KMSG_SYSTEM_EXIT: afs_remove_icon(); /* Try to remove the AFS plug-in action from Help menu if it was successfully registered. Also, delete the action. */ if (action_id_afs_help != 0) { khui_menu_def * help_menu; khm_boolean menu_changed = FALSE; khui_action_lock(); help_menu = khui_find_menu(KHUI_MENU_HELP); if (help_menu) { khm_size s; khm_size i; s = khui_menu_get_size(help_menu); for (i=0; i < s; i++) { khui_action_ref * aref = khui_menu_get_action(help_menu, i); if (aref && !(aref->flags & KHUI_ACTIONREF_PACTION) && aref->action == action_id_afs_help) { khui_menu_remove_action(help_menu, i); menu_changed = TRUE; break; } } } khui_action_delete(action_id_afs_help); khui_action_unlock(); if (menu_changed) khui_refresh_actions(); action_id_afs_help = 0; } if (afs_msg_type_id != -1) { kmq_unsubscribe(afs_msg_type_id, afs_plugin_cb); kmq_unregister_type(afs_msg_type_id); } if(afs_credtype_id >= 0) { kcdb_credtype_unregister(afs_credtype_id); } #if 0 if(afs_attr_client >= 0) { kcdb_attrib_unregister(afs_attr_client); } #endif if(afs_attr_cell >= 0) { kcdb_attrib_unregister(afs_attr_cell); } if(afs_attr_realm >= 0) { kcdb_attrib_unregister(afs_attr_realm); } if(afs_attr_method >= 0) { kcdb_attrib_unregister(afs_attr_method); } if(afs_attr_client_princ >= 0) { kcdb_attrib_unregister(afs_attr_client_princ); } if(afs_attr_server_princ >= 0) { kcdb_attrib_unregister(afs_attr_server_princ); } if(afs_type_principal >= 0) { kcdb_type_unregister(afs_type_principal); } if(afs_type_method >= 0) { kcdb_type_unregister(afs_type_method); } initialized = FALSE; if(afs_credset) kcdb_credset_delete(afs_credset); /* afs_sub doesn't need to be deleted. That is taken care of when unregistering the afs cred type */ afs_sub = NULL; #if KH_VERSION_API < 7 if (hm_netidmgr) FreeLibrary(hm_netidmgr); pkhui_action_lock = NULL; pkhui_action_unlock = NULL; pkhui_refresh_actions = NULL; pkhui_request_UI_callback = NULL; #endif rv = KHM_ERROR_SUCCESS; break; /* end of KMSG_SYSTEM_EXIT */ } return rv; }
void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count) { int zeny = 0; unsigned int i, weight, listidx, k; struct map_session_data* pl_sd; if( count == 0 ) {// nothing to do return; } if( !battle_config.feature_buying_store || pc_istrading(sd) ) {// not allowed to sell clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } if( !pc->can_give_items(sd) ) {// custom: GM is not allowed to sell clif->message(sd->fd, msg_txt(246)); clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } if( ( pl_sd = iMap->id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id ) {// not online, not buying or not same store clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } if( !searchstore->queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) ) {// out of view range clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } searchstore->clearremote(sd); if( pl_sd->status.zeny < pl_sd->buyingstore.zenylimit ) {// buyer lost zeny in the mean time? fix the limit pl_sd->buyingstore.zenylimit = pl_sd->status.zeny; } weight = pl_sd->weight; // check item list for( i = 0; i < count; i++ ) {// itemlist: <index>.W <name id>.W <amount>.W unsigned short nameid, amount; int index; index = RBUFW(itemlist,i*6+0)-2; nameid = RBUFW(itemlist,i*6+2); amount = RBUFW(itemlist,i*6+4); if( i ) {// duplicate check. as the client does this too, only malicious intent should be caught here ARR_FIND( 0, i, k, RBUFW(itemlist,k*6+0)-2 == index ); if( k != i ) {// duplicate ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id); clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } } if( index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount ) {// invalid input clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc->get_group_level(sd), pc->get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) ) {// non-tradable item clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid ); if( listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0 ) {// there is no such item or the buyer has already bought all of them clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( pl_sd->buyingstore.items[listidx].amount < amount ) {// buyer does not need that much of the item clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid); return; } if( pc->checkadditem(pl_sd, nameid, amount) == ADDITEM_OVERAMOUNT ) {// buyer does not have enough space for this item clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( amount*(unsigned int)sd->inventory_data[index]->weight > pl_sd->max_weight-weight ) {// normally this is not supposed to happen, as the total weight is // checked upon creation, but the buyer could have gained items clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } weight+= amount*sd->inventory_data[index]->weight; if( amount*pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit-zeny ) {// buyer does not have enough zeny clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid); return; } zeny+= amount*pl_sd->buyingstore.items[listidx].price; } // process item list for( i = 0; i < count; i++ ) {// itemlist: <index>.W <name id>.W <amount>.W unsigned short nameid, amount; int index; index = RBUFW(itemlist,i*6+0)-2; nameid = RBUFW(itemlist,i*6+2); amount = RBUFW(itemlist,i*6+4); ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid ); zeny = amount*pl_sd->buyingstore.items[listidx].price; // move item pc->additem(pl_sd, &sd->status.inventory[index], amount, LOG_TYPE_BUYING_STORE); pc->delitem(sd, index, amount, 1, 0, LOG_TYPE_BUYING_STORE); pl_sd->buyingstore.items[listidx].amount-= amount; // pay up pc->payzeny(pl_sd, zeny, LOG_TYPE_BUYING_STORE, sd); pc->getzeny(sd, zeny, LOG_TYPE_BUYING_STORE, pl_sd); pl_sd->buyingstore.zenylimit-= zeny; // notify clients clif->buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price); clif->buyingstore_update_item(pl_sd, nameid, amount); } if( iMap->save_settings&128 ) { chrif_save(sd, 0); chrif_save(pl_sd, 0); } // check whether or not there is still something to buy ARR_FIND( 0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0 ); if( i == pl_sd->buyingstore.slots ) {// everything was bought clif->buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS); } else if( pl_sd->buyingstore.zenylimit == 0 ) {// zeny limit reached clif->buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY); } else {// continue buying return; } // cannot continue buying buyingstore_close(pl_sd); // remove auto-trader if( pl_sd->state.autotrade ) { iMap->quit(pl_sd); } }
/*========================================== * path search (x0,y0)->(x1,y1) * wpd: path info will be written here * flag: &1 = easy path search only * cell: type of obstruction to check for *------------------------------------------*/ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell) { register int i, j, x, y, dx, dy; struct map_data *md; struct walkpath_data s_wpd; if (wpd == NULL) wpd = &s_wpd; // use dummy output variable if (!map[m].cell) return false; md = &map[m]; #ifdef CELL_NOSTACK //Do not check starting cell as that would get you stuck. if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys) #else if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| md->getcellp(md,x0,y0,cell)*/) #endif return false; // Check destination cell if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || md->getcellp(md,x1,y1,cell)) return false; if (flag&1) { // Try finding direct path to target // Direct path goes diagonally first, then in straight line. // calculate (sgn(x1-x0), sgn(y1-y0)) dx = ((dx = x1-x0)) ? ((dx<0) ? -1 : 1) : 0; dy = ((dy = y1-y0)) ? ((dy<0) ? -1 : 1) : 0; x = x0; // Current position = starting cell y = y0; i = 0; while( i < ARRAYLENGTH(wpd->path) ) { wpd->path[i] = walk_choices[-dy + 1][dx + 1]; i++; x += dx; // Advance current position y += dy; if( x == x1 ) dx = 0; // destination x reached, no longer move along x-axis if( y == y1 ) dy = 0; // destination y reached, no longer move along y-axis if( dx == 0 && dy == 0 ) break; // success if( md->getcellp(md,x,y,cell) ) break; // obstacle = failure } if( x == x1 && y == y1 ) { // easy path successful. wpd->path_len = i; wpd->path_pos = 0; return true; } return false; // easy path unsuccessful } else { // !(flag&1) // A* (A-star) pathfinding // We always use A* for finding walkpaths because it is what game client uses. // Easy pathfinding cuts corners of non-walkable cells, but client always walks around it. BHEAP_STRUCT_VAR(node_heap, open_set); // 'Open' set // FIXME: This array is too small to ensure all paths shorter than MAX_WALKPATH // can be found without node collision: calc_index(node1) = calc_index(node2). // Figure out more proper size or another way to keep track of known nodes. struct path_node tp[MAX_WALKPATH * MAX_WALKPATH]; struct path_node *current, *it; int xs = md->xs - 1; int ys = md->ys - 1; int len = 0; memset(tp, 0, sizeof(tp)); // Start node i = calc_index(x0, y0); tp[i].parent = NULL; tp[i].x = x0; tp[i].y = y0; tp[i].g_cost = 0; tp[i].f_cost = heuristic(x0, y0, x1, y1); tp[i].flag = SET_OPEN; heap_push_node(&open_set, &tp[i]); // Put start node to 'open' set for(;;) { int e = 0; // error flag // Saves allowed directions for the current cell. Diagonal directions // are only allowed if both directions around it are allowed. This is // to prevent cutting corner of nearby wall. // For example, you can only go NW from the current cell, if you can // go N *and* you can go W. Otherwise you need to walk around the // (corner of the) non-walkable cell. int allowed_dirs = 0; int g_cost; if (BHEAP_LENGTH(open_set) == 0) { BHEAP_CLEAR(open_set); return false; } current = BHEAP_PEEK(open_set); // Look for the lowest f_cost node in the 'open' set BHEAP_POP(open_set, NODE_MINTOPCMP, swap_ptr); // Remove it from 'open' set x = current->x; y = current->y; g_cost = current->g_cost; current->flag = SET_CLOSED; // Add current node to 'closed' set if (x == x1 && y == y1) { BHEAP_CLEAR(open_set); break; } if (y < ys && !md->getcellp(md, x, y+1, cell)) allowed_dirs |= DIR_NORTH; if (y > 0 && !md->getcellp(md, x, y-1, cell)) allowed_dirs |= DIR_SOUTH; if (x < xs && !md->getcellp(md, x+1, y, cell)) allowed_dirs |= DIR_EAST; if (x > 0 && !md->getcellp(md, x-1, y, cell)) allowed_dirs |= DIR_WEST; #define chk_dir(d) ((allowed_dirs & (d)) == (d)) // Process neighbors of current node // TODO: Processing order affects chosen path if there is more than one path with same cost. // In few cases path found by server will be different than path found by game client. if (chk_dir(DIR_SOUTH)) e += add_path(&open_set, tp, x, y-1, g_cost + MOVE_COST, current, heuristic(x, y-1, x1, y1)); // (x, y-1) 4 if (chk_dir(DIR_SOUTH|DIR_WEST) && !md->getcellp(md, x-1, y-1, cell)) e += add_path(&open_set, tp, x-1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y-1, x1, y1)); // (x-1, y-1) 3 if (chk_dir(DIR_WEST)) e += add_path(&open_set, tp, x-1, y, g_cost + MOVE_COST, current, heuristic(x-1, y, x1, y1)); // (x-1, y) 2 if (chk_dir(DIR_NORTH|DIR_WEST) && !md->getcellp(md, x-1, y+1, cell)) e += add_path(&open_set, tp, x-1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y+1, x1, y1)); // (x-1, y+1) 1 if (chk_dir(DIR_NORTH)) e += add_path(&open_set, tp, x, y+1, g_cost + MOVE_COST, current, heuristic(x, y+1, x1, y1)); // (x, y+1) 0 if (chk_dir(DIR_NORTH|DIR_EAST) && !md->getcellp(md, x+1, y+1, cell)) e += add_path(&open_set, tp, x+1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y+1, x1, y1)); // (x+1, y+1) 7 if (chk_dir(DIR_EAST)) e += add_path(&open_set, tp, x+1, y, g_cost + MOVE_COST, current, heuristic(x+1, y, x1, y1)); // (x+1, y) 6 if (chk_dir(DIR_SOUTH|DIR_EAST) && !md->getcellp(md, x+1, y-1, cell)) e += add_path(&open_set, tp, x+1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y-1, x1, y1)); // (x+1, y-1) 5 #undef chk_dir if (e) { BHEAP_CLEAR(open_set); return false; } } for (it = current; it->parent != NULL; it = it->parent, len++); if (len > sizeof(wpd->path)) { return false; } // Recreate path wpd->path_len = len; wpd->path_pos = 0; for (it = current, j = len-1; j >= 0; it = it->parent, j--) { dx = it->x - it->parent->x; dy = it->y - it->parent->y; wpd->path[j] = walk_choices[-dy + 1][dx + 1]; } return true; } // A* end return false; }
// ギルドエンブレム変更通知 int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) { int i; struct map_session_data *sd; struct guild *g=guild_search(guild_id); if(g==NULL) return 0; memcpy(g->emblem_data,data,len); g->emblem_len=len; g->emblem_id=emblem_id; for(i=0;i<g->max_member;i++){ if((sd=g->member[i].sd)!=NULL){ sd->guild_emblem_id=emblem_id; clif_guild_belonginfo(sd,g); clif_guild_emblem(sd,g); clif_guild_emblem_area(&sd->bl); } } {// update guardians (mobs) DBIterator* iter = db_iterator(castle_db); struct guild_castle* gc; for( gc = (struct guild_castle*)dbi_first(iter) ; dbi_exists(iter); gc = (struct guild_castle*)dbi_next(iter) ) { if( gc->guild_id != guild_id ) continue; // update permanent guardians for( i = 0; i < ARRAYLENGTH(gc->guardian); ++i ) { TBL_MOB* md = (gc->guardian[i].id ? map_id2md(gc->guardian[i].id) : NULL); if( md == NULL || md->guardian_data == NULL ) continue; md->guardian_data->emblem_id = emblem_id; clif_guild_emblem_area(&md->bl); } // update temporary guardians for( i = 0; i < gc->temp_guardians_max; ++i ) { TBL_MOB* md = (gc->temp_guardians[i] ? map_id2md(gc->temp_guardians[i]) : NULL); if( md == NULL || md->guardian_data == NULL ) continue; md->guardian_data->emblem_id = emblem_id; clif_guild_emblem_area(&md->bl); } } dbi_destroy(iter); } {// update npcs (flags or other npcs that used flagemblem to attach to this guild) // TODO this is not efficient [FlavioJS] struct s_mapiterator* iter = mapit_geteachnpc(); TBL_NPC* nd; for( nd = (TBL_NPC*)mapit_first(iter) ; mapit_exists(iter); nd = (TBL_NPC*)mapit_next(iter) ) { if( nd->subtype != SCRIPT || nd->u.scr.guild_id != guild_id ) continue; clif_guild_emblem_area(&nd->bl); } mapit_free(iter); } return 0; }
khm_int32 krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam) { switch(msg_subtype) { case KMSG_CRED_NEW_CREDS: { khui_new_creds * nc; khui_new_creds_by_type * nct; khm_size cbsize; wchar_t wbuf[256]; nc = (khui_new_creds *) vparam; nct = PMALLOC(sizeof(*nct)); #ifdef DEBUG assert(nct); #endif ZeroMemory(nct, sizeof(*nct)); nct->type = credtype_id_krb4; nct->ordinal = 3; LoadString(hResModule, IDS_NC_K4_SHORT, wbuf, ARRAYLENGTH(wbuf)); StringCbLength(wbuf, sizeof(wbuf), &cbsize); cbsize += sizeof(wchar_t); nct->name = PMALLOC(cbsize); StringCbCopy(nct->name, cbsize, wbuf); nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; nct->h_module = hResModule; nct->dlg_proc = k4_nc_dlg_proc; nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4); khui_cw_add_type(nc, nct); } break; case KMSG_CRED_RENEW_CREDS: { khui_new_creds * nc; khui_new_creds_by_type * nct; khm_size cbsize; wchar_t wbuf[256]; khui_action_context * pctx = NULL; nc = (khui_new_creds *) vparam; pctx = khui_cw_get_ctx(nc); if (!pctx->identity) break; nct = PMALLOC(sizeof(*nct)); #ifdef DEBUG assert(nct); #endif ZeroMemory(nct, sizeof(*nct)); nct->type = credtype_id_krb4; nct->ordinal = 3; LoadString(hResModule, IDS_NC_K4_SHORT, wbuf, ARRAYLENGTH(wbuf)); StringCbLength(wbuf, sizeof(wbuf), &cbsize); cbsize += sizeof(wchar_t); nct->name = PMALLOC(cbsize); StringCbCopy(nct->name, cbsize, wbuf); nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; khui_cw_add_type(nc, nct); } break; case KMSG_CRED_DIALOG_SETUP: break; case KMSG_CRED_PROCESS: { khui_new_creds * nc; khui_new_creds_by_type * nct = NULL; khm_handle ident = NULL; khui_action_context * pctx = NULL; k4_dlg_data * d = NULL; long code = 0; wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; khm_size cb; khm_int32 subtype; nc = (khui_new_creds *) vparam; if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) break; subtype = khui_cw_get_subtype(nc); if (subtype == KMSG_CRED_NEW_CREDS || subtype == KMSG_CRED_RENEW_CREDS) { khm_int32 method; if (subtype == KMSG_CRED_NEW_CREDS) { d = (k4_dlg_data *) nct->aux; if (KHM_FAILED(khui_cw_get_primary_id(nc, &ident))) break; if (!d || khui_cw_get_result(nc) != KHUI_NC_RESULT_PROCESS) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); kcdb_identity_release(ident); break; } if (!d->k4_enabled) { k4_write_identity_data(d); khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); kcdb_identity_release(ident); break; } method = d->method; cb = sizeof(idname); kcdb_identity_get_name(ident, idname, &cb); _begin_task(0); _report_sr0(KHERR_NONE, IDS_MSG_K4NEW); _resolve(); _describe(); } else if (subtype == KMSG_CRED_RENEW_CREDS) { pctx = khui_cw_get_ctx(nc); if ((pctx->scope == KHUI_SCOPE_IDENT && pctx->identity != NULL) || (pctx->scope == KHUI_SCOPE_CREDTYPE && pctx->cred_type == credtype_id_krb4 && pctx->identity != NULL) || (pctx->scope == KHUI_SCOPE_CRED && pctx->cred_type == credtype_id_krb4 && pctx->identity != NULL && pctx->cred != NULL)) { ident = pctx->identity; kcdb_identity_hold(ident); if (!k4_should_identity_get_k4(ident)) { _reportf(L"Kerberos 4 is not enabled for this identity. Skipping"); khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); kcdb_identity_release(ident); break; } } else { _reportf(L"Kerberos 4 is not within renewal scope. Skipping"); khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); break; } method = K4_METHOD_K524; /* only k524 is supported for renewals */ _begin_task(0); cb = sizeof(idname); kcdb_identity_get_name(ident, idname, &cb); _report_sr0(KHERR_NONE, IDS_MSG_K4RENEW); _resolve(); _describe(); } else { assert(FALSE); break; } _progress(0,1); if ((method == K4_METHOD_AUTO || method == K4_METHOD_K524) && khui_cw_type_succeeded(nc, credtype_id_krb5)) { khm_handle tgt; FILETIME ft_prev; FILETIME ft_new; khm_size cb; _report_cs0(KHERR_INFO, L"Trying K524..."); tgt = khm_krb4_find_tgt(NULL, ident); _progress(1,3); if (tgt) { cb = sizeof(ft_prev); if (KHM_FAILED(kcdb_cred_get_attr(tgt, KCDB_ATTR_EXPIRE, NULL, &ft_prev, &cb))) ZeroMemory(&ft_prev, sizeof(ft_prev)); kcdb_cred_release(tgt); } code = khm_convert524(ident); _progress(2,3); _reportf(L"khm_convert524 returns code %d", code); if (code == 0) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); if (subtype == KMSG_CRED_NEW_CREDS) { assert(d != NULL); k4_write_identity_data(d); } else if (subtype == KMSG_CRED_RENEW_CREDS && (pctx->scope == KHUI_SCOPE_CREDTYPE || pctx->scope == KHUI_SCOPE_CRED)) { khm_krb4_list_tickets(); tgt = khm_krb4_find_tgt(NULL, ident); if (tgt) { cb = sizeof(ft_new); ZeroMemory(&ft_new, sizeof(ft_new)); kcdb_cred_get_attr(tgt, KCDB_ATTR_EXPIRE, NULL, &ft_new, &cb); kcdb_cred_release(tgt); } if (!tgt || CompareFileTime(&ft_new, &ft_prev) <= 0) { /* The new TGT wasn't much of an improvement over what we already had. We should go out and try to renew the identity now. */ khui_action_context ctx; _reportf(L"Renewal of Krb4 creds failed to get a longer TGT. Triggering identity renewal"); khui_context_create(&ctx, KHUI_SCOPE_IDENT, pctx->identity, KCDB_CREDTYPE_INVALID, NULL); khui_action_trigger(KHUI_ACTION_RENEW_CRED, &ctx); khui_context_release(&ctx); } } _progress(1,1); _end_task(); if (ident) kcdb_identity_release(ident); break; } else if (method == K4_METHOD_K524) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); if (subtype == KMSG_CRED_RENEW_CREDS && (pctx->scope == KHUI_SCOPE_CREDTYPE || pctx->scope == KHUI_SCOPE_CRED)) { /* We were trying to get a new Krb4 TGT for this identity. Sometimes this fails because of restrictions placed on K524d regarding the lifetime of the issued K4 TGT. In this case, we trigger a renewal of the identity in the hope that the new K5 TGT will allow us to successfully get a new K4 TGT next time over using the new K5 TGT. */ khui_action_context ctx; _reportf(L"Renewal of Krb4 creds failed using k524. Triggerring identity renewal."); khui_context_create(&ctx, KHUI_SCOPE_IDENT, pctx->identity, KCDB_CREDTYPE_INVALID, NULL); khui_action_trigger(KHUI_ACTION_RENEW_CRED, &ctx); khui_context_release(&ctx); } _progress(1,1); _end_task(); if (ident) kcdb_identity_release(ident); break; } } /* only supported for new credentials */ if (method == K4_METHOD_AUTO || method == K4_METHOD_PASSWORD) { khm_size n_prompts = 0; khm_size idx; khm_size cb; wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE]; char pwd[KHUI_MAXCCH_PROMPT_VALUE]; wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; char idname[KCDB_IDENT_MAXCCH_NAME]; char * aname = NULL; char * inst = NULL; char * realm = NULL; assert(subtype == KMSG_CRED_NEW_CREDS); _report_cs0(KHERR_INFO, L"Trying password ..."); code = TRUE; /* just has to be non-zero */ khui_cw_get_prompt_count(nc, &n_prompts); if (n_prompts == 0) goto _skip_pwd; for (idx = 0; idx < n_prompts; idx++) { khui_new_creds_prompt * p; if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p))) continue; if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD) break; } if (idx >= n_prompts) { _reportf(L"Password prompt not found"); goto _skip_pwd; } khui_cw_sync_prompt_values(nc); cb = sizeof(wpwd); if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx, wpwd, &cb))) { _reportf(L"Failed to obtain password value"); goto _skip_pwd; } UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd); cb = sizeof(widname); kcdb_identity_get_name(ident, widname, &cb); UnicodeStrToAnsi(idname, sizeof(idname), widname); { char * atsign; atsign = strchr(idname, '@'); if (atsign == NULL) { _reportf(L"Identity name does not contain an '@'"); goto _skip_pwd; } *atsign++ = 0; realm = atsign; } { char * slash; slash = strchr(idname, '/'); if (slash != NULL) { *slash++ = 0; inst = slash; } else { inst = ""; } } aname = idname; code = khm_krb4_kinit(aname, inst, realm, (long) d->lifetime, pwd); _progress(2,3); _reportf(L"khm_krb4_kinit returns code %d", code); _skip_pwd: if (code) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_EXIT | KHUI_NC_RESPONSE_FAILED); } else { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_EXIT | KHUI_NC_RESPONSE_SUCCESS); if (subtype == KMSG_CRED_NEW_CREDS) { assert(d != NULL); k4_write_identity_data(d); } } } _progress(1,1); _end_task(); } if (ident) kcdb_identity_release(ident); } break; case KMSG_CRED_END: { khui_new_creds * nc; khui_new_creds_by_type * nct = NULL; nc = (khui_new_creds *) vparam; if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) break; khui_cw_del_type(nc, credtype_id_krb4); if (nct->name) PFREE(nct->name); if (nct->credtext) PFREE(nct->credtext); PFREE(nct); } break; } return KHM_ERROR_SUCCESS; }