void handle_D9( Network::Client* client, PKTIN_D9* msg ) { PKTIN_D9 _msg; // got crashes here under *nix -> modify a new local instance // Transform Little-Endian <-> Big-Endian _msg.instance = cfBEu32( msg->instance ); // Unique Instance ID of UO _msg.os_major = cfBEu32( msg->os_major ); // OS Major _msg.os_minor = cfBEu32( msg->os_minor ); // OS Minor _msg.os_revision = cfBEu32( msg->os_revision ); // OS Revision _msg.cpu_family = cfBEu32( msg->cpu_family ); // CPU Family _msg.cpu_model = cfBEu32( msg->cpu_model ); // CPU Model _msg.cpu_clockspeed = cfBEu32( msg->cpu_clockspeed ); // CPU Clock Speed [Mhz] _msg.memory = cfBEu32( msg->memory ); // Memory [MB] _msg.screen_width = cfBEu32( msg->screen_width ); // Screen Width _msg.screen_height = cfBEu32( msg->screen_height ); // Screen Height _msg.screen_depth = cfBEu32( msg->screen_depth ); // Screen Depth [Bit] _msg.directx_major = cfBEu16( msg->directx_major ); // DirectX Major _msg.directx_minor = cfBEu16( msg->directx_minor ); // DirectX Minor for ( unsigned i = 0; i < sizeof( msg->video_description ) / sizeof( msg->video_description[0] ); ++i ) _msg.video_description[i] = cfBEu16( msg->video_description[i] ); // Video Card Description [wide-character] _msg.video_vendor = cfBEu32( msg->video_vendor ); // Video Card Vendor ID _msg.video_device = cfBEu32( msg->video_device ); // Video Card Device ID _msg.video_memory = cfBEu32( msg->video_memory ); // Video Card Memory [MB] for ( unsigned i = 0; i < sizeof( msg->langcode ) / sizeof( msg->langcode[0] ); ++i ) _msg.langcode[i] = cfBEu16( msg->langcode[i] ); // Language Code [wide-character] client->setclientinfo( &_msg ); }
void handle_menu_selection( Network::Client *client, PKTIN_7D *msg ) { if ( client->chr->menu == NULL ) { POLLOG.Format( "{}/{} tried to use a menu, but none was active.\n" ) << client->acct->name() << client->chr->name(); return; } u16 menu_id = cfBEu16( msg->menu_id ); if ( client->chr->menu->menu_id != menu_id ) { INFO_PRINT << "Client tried to use a menu he wasn't entitled to\n"; // LOGME illegal menu selection client->chr->cancel_menu(); return; } Menu* menu = client->chr->menu; client->chr->menu = NULL; if ( msg->choice == 0 ) // client cancelled menu { client->chr->cancel_menu(); return; } u16 choice = cfBEu16( msg->choice ); if ( choice == 0 || choice > menu->menuitems_.size() ) { INFO_PRINT << "Client menu choice out of range\n"; client->chr->cancel_menu(); return; } // Wow, client chose something valid from the menu, even. // Note, the incoming message specified object type, color, and used_item_serial. // Since we'd just have to verify these anyway, I'm just going // to ignore them, and use the information in the MenuItem. // If this turns out not to be workable, we'll have to validate those // input fields, too. MenuItem* mi = &menu->menuitems_[choice - 1]; if ( mi->submenu_id ) { client->chr->menu = Menu::find_menu( mi->submenu_id ); send_menu( client, client->chr->menu ); } else { passert( client->chr->on_menu_selection ); client->chr->on_menu_selection( client, mi, msg ); } }
void handle_prompt( Network::Client* client, PKTBI_9A* msg ) { Module::UOExecutorModule* uoemod = client->gd->prompt_uoemod; if ( uoemod == nullptr ) return; int textlen = cfBEu16( msg->msglen ) - offsetof( PKTBI_9A, text ); if ( msg->type ) { if ( textlen <= 120 && msg->text[textlen - 1] == '\0' ) { bool ok = true; --textlen; // don't include null terminator (already checked) for ( int i = 0; i < textlen; ++i ) { if ( !isprint( msg->text[i] ) ) { ok = false; break; } } if ( ok ) { Bscript::String* str = new Bscript::String( msg->text, textlen ); uoemod->uoexec.ValueStack.back().set( new Bscript::BObject( str ) ); } } } uoemod->uoexec.revive(); uoemod->prompt_chr = nullptr; client->gd->prompt_uoemod = nullptr; }
void handle_client_version( Client* client, PKTBI_BD* msg ) { u16 len = cfBEu16(msg->msglen)-3; if (len < 100) { int c=0; char ch; string ver2 =""; while (c<len) { ch = msg->version[c]; if (ch==0) break; // seems to be null-terminated ver2+=ch; ++c; } client->setversion( ver2 ); VersionDetailStruct vers_det; client->itemizeclientversion(ver2, vers_det); client->setversiondetail(vers_det); if (client->compareVersion(CLIENT_VER_7000)) client->setClientType(CLIENTTYPE_7000); else if (client->compareVersion(CLIENT_VER_60142)) client->setClientType(CLIENTTYPE_60142); else if (client->compareVersion(CLIENT_VER_6017)) //Grid-loc support client->setClientType(CLIENTTYPE_6017); else if (client->compareVersion(CLIENT_VER_5020)) client->setClientType(CLIENTTYPE_5020); else if (client->compareVersion(CLIENT_VER_5000)) client->setClientType(CLIENTTYPE_5000); else if (client->compareVersion(CLIENT_VER_4070)) client->setClientType(CLIENTTYPE_4070); else if (client->compareVersion(CLIENT_VER_4000)) client->setClientType(CLIENTTYPE_4000); if (ssopt.core_sends_season) send_season_info( client ); // Scott 10/11/2007 added for login fixes and handling 1.x clients. // Season info needs to check client version to keep from crashing 1.x // version not set until shortly after login complete. //send_feature_enable(client); //dave commented out 8/21/03, unexpected problems with people sending B9 via script with this too. if( (client->UOExpansionFlag & AOS) ) { send_object_cache(client, dynamic_cast<const UObject*>(client->chr)); } } else { Log2( "Suspect string length in PKTBI_BD packet: %u\n", (unsigned) len ); } }
bool convertUCtoArray( const u16* in_wtext, Bscript::ObjArray*& out_text, size_t textlen, bool ConvFromBE /*false*/ ) { u16 value; out_text = new Bscript::ObjArray( ); for( size_t i = 0; i < textlen; i++ ) { value = ConvFromBE ? cfBEu16( in_wtext[i] ) : in_wtext[i]; // Jump out on a NULL (EOS) value (should stop exploits, too?) if( value == 0L ) return true; out_text->addElement( new Bscript::BLong( value ) ); } return true; }
void handle_se_object_list( Client* client, PKTBI_D6_IN* msgin ) { UObject* obj = NULL; int length=cfBEu16(msgin->msglen)-3; if ( length < 0 || (length%4) != 0 ) return; int count = length/4; for( int i = 0; i < count; ++i ) { obj = system_find_object(cfBEu32( msgin->serials[i].serial )); if (obj != NULL) SendAOSTooltip(client,obj); } }
void handle_skill_lock( Network::Client* client, PKTBI_3A_LOCKS* msg ) { if ( settingsManager.ssopt.core_handled_locks ) { unsigned int skillid = cfBEu16( msg->skillid ); if ( skillid > networkManager.uoclient_general.maxskills ) return; const UOSkill& uoskill = GetUOSkill( skillid ); if ( !uoskill.pAttr ) // tried to set lockstate for a skill that isn't defined return; if ( msg->lock_mode < 3 ) client->chr->attribute( uoskill.pAttr->attrid ).lock( msg->lock_mode ); else INFO_PRINT << "Client " << client->chr->name() << " tried to set an illegal lock state.\n"; } }
void handle_get_tip( Client* client, PKTIN_A7* msg ) { u16 tipnum = cfBEu16( msg->lasttip ); if (tipfilenames.size()) { if (msg->prevnext) { ++tipnum; if (tipnum >= tipfilenames.size()) tipnum = 0; } else { --tipnum; if (tipnum >= tipfilenames.size()) tipnum = static_cast<u16>(tipfilenames.size()) - 1; } send_tip( client, tipfilenames[tipnum].c_str(), tipnum ); } }
void select_server( Network::Client* client, PKTIN_A0* msg ) // Relay player to a certain IP { unsigned servernum = cfBEu16( msg->servernum ) - 1; if ( servernum >= networkManager.servers.size() ) { client->forceDisconnect(); return; } ServerDescription* svr = networkManager.servers[servernum]; Network::PktHelper::PacketOut<Network::PktOut_8C> rsp; rsp->Write<u8>( svr->ip[3] ); rsp->Write<u8>( svr->ip[2] ); rsp->Write<u8>( svr->ip[1] ); rsp->Write<u8>( svr->ip[0] ); if ( client->listen_port != 0 ) rsp->WriteFlipped<u16>( client->listen_port ); else rsp->WriteFlipped<u16>( svr->port ); // MuadDib Added new seed system. This is for transferring KR/6017/Normal client detection from // loginserver // to the gameserver. Allows keeping client flags from remote loginserver to gameserver for 6017 // and kr // packets. unsigned int nseed = 0xFEFE0000 | client->ClientType; rsp->WriteFlipped<u32>( nseed ); // This was set to 0xffffffff in the past but this will conflict // with UO:KR detection rsp.Send( client ); client->cryptengine->Init( &nseed, Crypt::CCryptBase::typeGame ); }
void login2( Network::Client* client, PKTIN_91* msg ) // Gameserver login and character listing { client->encrypt_server_stream = true; if ( Network::is_banned_ip( client ) ) { send_login_error( client, LOGIN_ERROR_ACCOUNT_BLOCKED ); client->Disconnect(); return; } /* Hmm, might have to re-search for account. For now, we already have the account in client->acct. Might work different if real loginservers were used. */ Accounts::Account* acct = Accounts::find_account( msg->name ); if ( acct == nullptr ) { send_login_error( client, LOGIN_ERROR_NO_ACCOUNT ); client->Disconnect(); return; } // First check the password - if wrong, you can't find out anything else. bool correct_password = false; // dave changed 6/5/3, always authenticate with hashed user+pass std::string msgpass = msg->password; std::string acctname = acct->name(); std::string temp; Clib::MD5_Encrypt( acctname + msgpass, temp ); // MD5 correct_password = Clib::MD5_Compare( acct->passwordhash(), temp ); if ( !correct_password ) { send_login_error( client, LOGIN_ERROR_WRONG_PASSWORD ); client->Disconnect(); POLLOG.Format( "Incorrect password for account {} from {}\n" ) << acct->name() << client->ipaddrAsString(); return; } else { // write out cleartext if necessary if ( Plib::systemstate.config.retain_cleartext_passwords ) { if ( acct->password().empty() ) acct->set_password( msgpass ); } } if ( !acct->enabled() || acct->banned() ) { send_login_error( client, LOGIN_ERROR_ACCOUNT_BLOCKED ); client->Disconnect(); return; } // // Dave moved the max_clients check to pol.cpp so character cmdlevel could be checked. // POLLOG.Format( "Account {} logged in from {}\n" ) << acct->name() << client->ipaddrAsString(); // ENHANCEMENT: could authenticate with real loginservers. client->acct = acct; /* NOTE: acct->client is not set here. It is possible that another client is still connected, or a connection is stuck open, or similar. When a character is selected, if another client is connected, measures will be taken. */ // Tell the client about the starting locations and his characters (up to 5). // MuadDib Added new seed system. This is for transferring KR/6017/Normal client detection from // loginserver // to the gameserver. Allows keeping client flags from remote loginserver to gameserver for 6017 // and kr // packets. client->ClientType = cfBEu16( msg->unk3_4_ClientType ); send_start( client ); }
// This is for legacy up to 5.0(?). Cuz ML added new bytes in the middle of the packet. void send_full_statmsg_std( Client *client, Character *chr ) { PKTOUT_11_V1 msg; msg.msgtype = PKTOUT_11_V1_ID; if( (client->UOExpansionFlag & AOS) ) { msg.msglen = ctBEu16(sizeof msg); msg.moreinfo = 04; // Set to AOS level statbar for full info } else { unsigned short msglen = offsetof( PKTOUT_11_V1, statcap ); msg.msglen = ctBEu16(msglen); msg.moreinfo = 01; // Set to oldschool statbar info. } msg.serial = chr->serial_ext; strzcpy( msg.name, chr->name().c_str(), sizeof msg.name ); if (uoclient_general.hits.any) { long v = chr->vital(uoclient_general.hits.id).current_ones(); if (v > 0xFFFF) v = 0xFFFF; msg.hits = ctBEu16( static_cast<u16>(v) ); v = chr->vital(uoclient_general.hits.id).maximum_ones(); if (v > 0xFFFF) v = 0xFFFF; msg.max_hits = ctBEu16( static_cast<u16>(v) ); } else { msg.hits = 0; msg.max_hits = 0; } msg.renameable = 0; // (client->chr->can_rename( chr ) ? 0xFF : 0); //if (chr->race == RACE_ELF) // msg.gender = static_cast<u8>(chr->gender | FLAG_RACE); //else msg.gender = static_cast<u8>(chr->gender); if (uoclient_general.strength.any) { long v = chr->attribute(uoclient_general.strength.id).effective(); if (v > 0xFFFF) v = 0xFFFF; msg.str = ctBEu16( static_cast<u16>(v) ); } else { msg.str = 0; } if (uoclient_general.dexterity.any) { long v = chr->attribute(uoclient_general.dexterity.id).effective(); if (v > 0xFFFF) v = 0xFFFF; msg.dex = ctBEu16( static_cast<u16>(v) ); } else { msg.dex = 0; } if (uoclient_general.intelligence.any) { long v = chr->attribute(uoclient_general.intelligence.id).effective(); if (v > 0xFFFF) v = 0xFFFF; msg.intel = ctBEu16( static_cast<u16>(v) ); } else { msg.intel = 0; } if (uoclient_general.stamina.any) { long v = chr->vital(uoclient_general.stamina.id).current_ones(); if (v > 0xFFFF) v = 0xFFFF; msg.stamina = ctBEu16( static_cast<u16>(v) ); v = chr->vital( uoclient_general.stamina.id ).maximum_ones(); if (v > 0xFFFF) v = 0xFFFF; msg.max_stamina = ctBEu16( static_cast<u16>(v) ); } else { msg.stamina = 0; msg.max_stamina = 0; } if (uoclient_general.mana.any) { long v = chr->vital(uoclient_general.mana.id).current_ones(); if (v > 0xFFFF) v = 0xFFFF; msg.mana = ctBEu16( static_cast<u16>(v) ); v = chr->vital(uoclient_general.mana.id).maximum_ones(); if (v > 0xFFFF) v = 0xFFFF; msg.max_mana = ctBEu16( static_cast<u16>(v) ); } else { msg.mana = 0; msg.max_mana = 0; } msg.gold = ctBEu32( chr->gold_carried() ); // Adjusted to work with Physical Resist if AOS client, and AOS Resistances enabled. if( (client->UOExpansionFlag & AOS) && client->aosresist ) msg.AR = (chr->element_resist.physical < 0)?ctBEu16(0x10000+chr->element_resist.physical):ctBEu16(chr->element_resist.physical); else msg.AR = ctBEu16( chr->ar() ); msg.weight = ctBEu16( static_cast<u16>(chr->weight()) ); if ( msg.moreinfo >= 4 ) { msg.statcap = ctBEu16( chr->expanded_statbar.statcap ); msg.followers = chr->expanded_statbar.followers; msg.followers_max = chr->expanded_statbar.followers_max; msg.fireresist = (chr->element_resist.fire < 0)?ctBEu16(0x10000+chr->element_resist.fire):ctBEu16(chr->element_resist.fire); msg.coldresist = (chr->element_resist.cold < 0)?ctBEu16(0x10000+chr->element_resist.cold):ctBEu16(chr->element_resist.cold); msg.poisonresist = (chr->element_resist.poison < 0)?ctBEu16(0x10000+chr->element_resist.poison):ctBEu16(chr->element_resist.poison); msg.energyresist = (chr->element_resist.energy < 0)?ctBEu16(0x10000+chr->element_resist.energy):ctBEu16(chr->element_resist.energy); msg.luck = ctBEu16( chr->expanded_statbar.luck ); msg.damage_min = ctBEu16( chr->min_weapon_damage() ); msg.damage_max = ctBEu16( chr->max_weapon_damage() ); msg.titching = ctBEu32( chr->expanded_statbar.tithing ); } transmit(client, &msg, cfBEu16(msg.msglen) ); }
void handle_aos_commands (Client *client, PKTBI_D7* msg) { //cout <<" Sizeof: " << sizeof(PKTBI_D7) << endl; //cout << "Received AOS command: " << cfBEu16(msg->msglen) << " " << cfBEu16(msg->subcmd) << endl; //fdump (stdout, client->buffer, client->bytes_received); //should check if serial is valid? client->chr->serial == msg->serial? switch (cfBEu16(msg->subcmd)) { case PKTBI_D7::CUSTOM_HOUSE_BACKUP: CustomHousesBackup(msg); break; case PKTBI_D7::CUSTOM_HOUSE_RESTORE: CustomHousesRestore(msg); break; case PKTBI_D7::CUSTOM_HOUSE_COMMIT: CustomHousesCommit(msg); break; case PKTBI_D7::CUSTOM_HOUSE_ERASE: CustomHousesErase(msg); break; case PKTBI_D7::CUSTOM_HOUSE_ADD: CustomHousesAdd(msg); break; case PKTBI_D7::CUSTOM_HOUSE_QUIT: CustomHousesQuit(msg); break; case PKTBI_D7::CUSTOM_HOUSE_ADD_MULTI: CustomHousesAddMulti(msg); break; case PKTBI_D7::CUSTOM_HOUSE_SYNCH: CustomHousesSynch(msg); break; case PKTBI_D7::CUSTOM_HOUSE_CLEAR: CustomHousesClear(msg); break; case PKTBI_D7::CUSTOM_HOUSE_SELECT_FLOOR: CustomHousesSelectFloor(msg); break; case PKTBI_D7::CUSTOM_HOUSE_REVERT: CustomHousesRevert(msg); break; case PKTBI_D7::GUILD_BUTTON: OnGuildButton(client); break; case PKTBI_D7::QUEST_BUTTON: OnQuestButton(client); break; //missing combat book abilities default: handle_unknown_packet(client); } }
void handle_msg_BF( Client* client, PKTBI_BF* msg ) { UObject* obj = NULL; UMulti* multi = NULL; UHouse* house = NULL; switch(cfBEu16(msg->subcmd)) { case PKTBI_BF::TYPE_CLIENT_LANGUAGE: client->chr->uclang = strlower(msg->client_lang); break; case PKTBI_BF::TYPE_REQ_FULL_CUSTOM_HOUSE: if( (client->UOExpansionFlag & AOS) == 0 ) return; multi = system_find_multi(cfBEu32(msg->reqfullcustomhouse.house_serial)); if(multi != NULL) { house = multi->as_house(); if(house != NULL) { if(client->UOExpansionFlag & AOS) { send_object_cache(client, (UObject*)(house)); } //consider sending working design to certain players, to assist building, or GM help CustomHousesSendFull( house, client, HOUSE_DESIGN_CURRENT ); } } break; case PKTBI_BF::TYPE_OBJECT_CACHE: if( (client->UOExpansionFlag & AOS) == 0) return; obj = system_find_object(cfBEu32(msg->objectcache.serial)); if(obj != NULL) { SendAOSTooltip(client,obj); } break; case PKTBI_BF::TYPE_SESPAM: return; break; case PKTBI_BF::TYPE_SPELL_SELECT: do_cast(client, cfBEu16(msg->spellselect.selected_spell) ); break; case PKTBI_BF::TYPE_CHARACTER_RACE_CHANGER: character_race_changer_handler( client, msg ); break; case PKTBI_BF::TYPE_PARTY_SYSTEM: party_cmd_handler( client, msg ); break; case PKTBI_BF::TYPE_EXTENDED_STATS_IN: ext_stats_in(client, msg); break; case PKTBI_BF::TYPE_CLOSED_STATUS_GUMP: return; break; case PKTBI_BF::TYPE_SCREEN_SIZE: return; break; case PKTBI_BF::TYPE_TOGGLE_FLYING: if (client->chr->race==RACE_GARGOYLE) { // FIXME: add checks if its possible to stand with new movemode client->chr->movemode = (MOVEMODE)(client->chr->movemode ^ MOVEMODE_FLY); send_move_mobile_to_nearby_cansee( client->chr ); send_goxyz( client, client->chr ); } break; case PKTBI_BF::TYPE_CLIENTTYPE: client->UOExpansionFlagClient = ctBEu32( msg->clienttype.clientflag ); break; default: handle_unknown_packet( client ); } }