void handle_ef_seed( Client *client, PKTIN_EF *msg ) { VersionDetailStruct detail; detail.major=cfBEu32(msg->ver_Major); detail.minor=cfBEu32(msg->ver_Minor); detail.rev=cfBEu32(msg->ver_Revision); detail.patch=cfBEu32(msg->ver_Patch); client->setversiondetail(detail); 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); // detail->patch is since 5.0.7 always numeric, so no need to make it complicated OSTRINGSTREAM os; os << detail.major << "." << detail.minor << "." << detail.rev << "." << detail.patch; client->setversion(OSTRINGSTREAM_STR(os)); }
void handle_e1_clienttype( Client *client, PKTIN_E1 *msg ) { switch (cfBEu32(msg->clienttype)) { case PKTIN_E1::CLIENTTYPE_KR: client->setClientType(CLIENTTYPE_UOKR); break; case PKTIN_E1::CLIENTTYPE_SA: client->setClientType(CLIENTTYPE_UOSA); break; default: printf( "Unknown client type send with packet 0xE1 : 0x%lx\n",cfBEu32(msg->clienttype)); break; } }
void handle_allnames( Client *client, PKTBI_98_IN *msg ) { u32 serial = cfBEu32( msg->serial ); Character *the_mob = find_character( serial ); if (the_mob != NULL) { if (!client->chr->is_visible_to_me(the_mob)) { return; } if (pol_distance(client->chr->x, client->chr->y, the_mob->x, the_mob->y) > 20) { return; } PKTBI_98_OUT allnames; allnames.msgtype = PKTBI_98_OUT_ID; allnames.msglen = ctBEu16(0x25); // 0x25 = 37. Static Length. allnames.serial = the_mob->serial_ext; strzcpy( allnames.name, the_mob->name().c_str(), sizeof allnames.name ); transmit( client, &allnames, sizeof allnames ); } else { return; } }
void srequest( Network::Client* client, PKTIN_34* msg ) { u32 serial = cfBEu32( msg->serial2 ); if ( msg->stattype == STATTYPE_STATWINDOW ) { if ( client->chr->serial == serial ) statrequest( client, serial ); else { Mobile::Character* bob = find_character( serial ); if ( bob == NULL ) return; if ( !client->chr->is_concealed_from_me( bob ) && client->chr->is_visible_to_me( bob ) ) { if ( pol_distance( client->chr->x, client->chr->y, bob->x, bob->y ) < 20 ) statrequest( client, serial ); } if ( client->chr->has_party() ) client->chr->party()->send_stat_to( client->chr, bob ); } } else if ( msg->stattype == STATTYPE_SKILLWINDOW ) skillrequest( client, serial ); }
void handle_delete_character( Network::Client* client, PKTIN_83* msg ) { u32 charidx = cfBEu32( msg->charidx ); if ( ( charidx >= Plib::systemstate.config.character_slots ) || ( client->acct == nullptr ) || ( client->acct->get_character( charidx ) == nullptr ) ) { send_login_error( client, LOGIN_ERROR_MISC ); client->Disconnect(); return; } Accounts::Account* acct = client->acct; Mobile::Character* chr = acct->get_character( charidx ); if ( chr->client != nullptr || ( !Plib::systemstate.config.allow_multi_clients_per_account && acct->has_active_characters() ) ) { send_login_error( client, LOGIN_ERROR_OTHER_CHAR_INUSE ); client->Disconnect(); return; } if ( can_delete_character( chr, DELETE_BY_PLAYER ) ) { call_ondelete_scripts( chr ); delete_character( acct, chr, charidx ); } send_start( client ); }
void NoLosCheckedTargetCursor::on_target_cursor( Mobile::Character* chr, PKTBI_6C* msgin ) { if ( msgin == NULL ) { ( *func )( chr, NULL ); return; } u32 selected_serial = cfBEu32( msgin->selected_serial ); UObject* uobj = find_toplevel_object( selected_serial ); // FIXME inefficient, but neither works well by itself. bool additlegal = false; if ( uobj == NULL ) uobj = find_legal_item( chr, selected_serial, &additlegal ); if ( uobj == NULL ) uobj = system_find_multi( selected_serial ); if ( uobj == NULL ) { if ( chr->client != NULL ) send_sysmessage( chr->client, "What you selected does not seem to exist." ); if ( inform_on_cancel_ ) ( *func )( chr, NULL ); return; } ( *func )( chr, uobj ); }
void handle_singleclick(Network::Client* client, PKTIN_09* msg) { u32 serial = cfBEu32( msg->serial ); if (client && client->chr) singleclick(client, serial); // TODO: report if someone tries to use singleclick without a connected char (should have been blocked) }
void TargetCursor::handle_target_cursor( Mobile::Character* chr, PKTBI_6C* msg ) { if ( msg->selected_serial != 0 ) // targetted something { if ( chr->dead() ) // but is dead { if ( chr->client != NULL ) send_sysmessage( chr->client, "I am dead and cannot do that." ); cancel( chr ); return; } if ( ( chr->frozen() || chr->paralyzed() ) && !chr->setting_enabled( "freemove" ) ) { if ( chr->client != NULL ) { if ( chr->frozen() ) private_say_above( chr, chr, "I am frozen and cannot do that." ); else if ( chr->paralyzed() ) private_say_above( chr, chr, "I am paralyzed and cannot do that." ); } cancel( chr ); return; } u32 selected_serial = cfBEu32( msg->selected_serial ); UObject* obj = system_find_object( selected_serial ); if ( obj != NULL && obj->script_isa( POLCLASS_MOBILE ) && !obj->script_isa( POLCLASS_NPC ) ) { Mobile::Character* targeted = find_character( selected_serial ); // check for when char is not logged on if ( targeted != NULL ) { if ( !chr->is_visible_to_me( targeted ) ) { cancel( chr ); return; } if ( msg->cursor_type == 1 ) { if ( ( JusticeRegion::RunNoCombatCheck( chr->client ) == true ) || ( JusticeRegion::RunNoCombatCheck( targeted->client ) == true ) ) { send_sysmessage( chr->client, "Combat is not allowed in this area." ); cancel( chr ); return; } } } } } if ( msg->x != 0xffff || msg->selected_serial != 0 ) on_target_cursor( chr, msg ); else cancel( chr ); }
void NoLosCharacterCursor::on_target_cursor( Mobile::Character* targetter, PKTBI_6C* msgin ) { if ( msgin == NULL ) return; u32 selected_serial = cfBEu32( msgin->selected_serial ); Mobile::Character* chr = find_character( selected_serial ); if ( chr != NULL ) ( *func )( targetter, chr ); }
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_rename_char( Client* client, PKTIN_75* msg ) { Character* chr = find_character( cfBEu32( msg->serial )); if (chr != NULL) { if (client->chr->can_rename( chr )) { msg->name[ sizeof msg->name-1 ] = '\0'; // check for legal characters for( char* p = msg->name; *p; p++ ) { // only allow: a-z, A-Z & spaces if ( *p != ' ' && !isalpha(*p) ) { char buffer[512]; sprintf(buffer, "Client #%lu (account %s) attempted an invalid rename (packet 0x%2.02x):", client->instance_, (client->acct != NULL) ? client->acct->name() : "unknown", msg->msgtype); cout << buffer << endl; fdump( stdout, msg->name, static_cast<int>(strlen(msg->name)) ); if (logfile) { Log("%s\n", buffer); fdump( logfile, msg->name, static_cast<int>(strlen(msg->name)) ); } *p = '\0'; send_sysmessage( client, "Invalid name!" ); return; //dave 12/26 if invalid name, do not apply to chr! } } chr->setname( msg->name ); } else { send_sysmessage( client, "I can't rename that." ); } } else { send_sysmessage( client, "I can't find that." ); } }
void NoLosUObjectCursor::on_target_cursor( Mobile::Character* targetter, PKTBI_6C* msgin ) { if ( msgin == NULL ) { ( *func )( targetter, NULL ); return; } u32 selected_serial = cfBEu32( msgin->selected_serial ); UObject* obj = system_find_object( selected_serial ); if ( obj ) { ( *func )( targetter, obj ); } else if ( inform_on_cancel_ ) { ( *func )( targetter, NULL ); } }
void ObjectHash::Reap() { // this is called every 2 seconds (approximately) // iterate through enough of the object hash that it will be swept entirely once every 30 minutes // 2 minutes = 120 seconds = 60 reap calls per sweep // 30 minutes = 1800 seconds = 900 reap calls per sweep // first, figure out how many objects to check: hs::size_type count = hash.size(); if ( count == 0 ) return; hs::size_type count_this = count / 60; if ( count_this < 1 ) count_this = 1; if ( reap_iterator == hash.end() ) reap_iterator = hash.begin(); while ( count_this-- ) { UObject* obj = ( *reap_iterator ).second.get(); // We want the objecthash to be the holder of the last reference to an // object when it is deleted - hence the ref_counted_count() check. if ( obj->orphan() && obj->ref_counted_count() == 1 ) { dirty_deleted.insert( cfBEu32( obj->serial_ext ) ); hash.erase( reap_iterator++ ); } else ++reap_iterator; if ( reap_iterator == hash.end() ) { reap_iterator = hash.begin(); if ( reap_iterator == hash.end() ) break; } } }
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 doubleclick( Network::Client* client, PKTIN_06* msg ) { u32 serial = cfBEu32( msg->serial ); u32 paperdoll_macro_flag = serial & 0x80000000Lu; serial &= ~0x80000000Lu; // keypress versus doubleclick switch? // the find_character would find this, but most of the time it's your own paperdoll. // this is special-cased for two reasons: // 1) it's commonly done // 2) ghosts can doubleclick ONLY their paperdoll. if ( serial == client->chr->serial ) { if ( !paperdoll_macro_flag ) { ScriptDef sd; sd.quickconfig( "scripts/misc/dblclickself.ecl" ); if ( sd.exists() ) { ref_ptr<Bscript::EScriptProgram> prog; prog = find_script2( sd, false, Plib::systemstate.config.cache_interactive_scripts ); if ( prog.get() != nullptr && client->chr->start_script( prog.get(), false ) ) { return; } } } send_paperdoll( client, client->chr ); return; } if ( client->chr->dblclick_wait() > read_gameclock() ) { private_say_above( client->chr, client->chr, "You must wait to use something again." ); return; } else client->chr->dblclick_wait( read_gameclock() + settingsManager.ssopt.dblclick_wait ); if ( IsCharacter( serial ) ) { if ( client->chr->dead() ) return; Mobile::Character* chr = find_character( serial ); if ( !chr ) return; if ( chr->isa( UOBJ_CLASS::CLASS_NPC ) ) { Mobile::NPC* npc = static_cast<Mobile::NPC*>( chr ); if ( npc->can_accept_event( EVID_DOUBLECLICKED ) ) { npc->send_event( new Module::SourcedEvent( EVID_DOUBLECLICKED, client->chr ) ); return; } } bool script_ran = false; ScriptDef sd; sd.quickconfig( "scripts/misc/dblclickother.ecl" ); if ( sd.exists() ) { ref_ptr<Bscript::EScriptProgram> prog; prog = find_script2( sd, false, Plib::systemstate.config.cache_interactive_scripts ); if ( prog.get() != nullptr ) script_ran = client->chr->start_script( prog.get(), false, new Module::ECharacterRefObjImp( chr ) ); } if ( !script_ran && inrange( client->chr, chr ) ) { // MuadDib Changed from a large if || || || to switch case. 1/4/2007 switch ( chr->graphic ) { case UOBJ_HUMAN_MALE: case UOBJ_HUMAN_FEMALE: case UOBJ_HUMAN_MALE_GHOST: case UOBJ_HUMAN_FEMALE_GHOST: case UOBJ_ELF_MALE: case UOBJ_ELF_FEMALE: case UOBJ_ELF_MALE_GHOST: case UOBJ_ELF_FEMALE_GHOST: case UOBJ_GARGOYLE_MALE: case UOBJ_GARGOYLE_FEMALE: case UOBJ_GARGOYLE_MALE_GHOST: case UOBJ_GARGOYLE_FEMALE_GHOST: case UOBJ_GAMEMASTER: case 0x3de: case 0x3df: case 0x3e2: send_paperdoll( client, chr ); break; } } return; } else // doubleclicked an item { // next, search worn items, items in the backpack, and items in the world. Items::Item* item = find_legal_item( client->chr, serial ); // next, check people's backpacks. (don't recurse down) // (not done yet) if ( item != nullptr ) { const Items::ItemDesc& id = item->itemdesc(); if ( !id.ghosts_can_use && client->chr->dead() ) { private_say_above( client->chr, client->chr, "I am dead and cannot do that." ); return; } if ( !id.can_use_while_frozen && client->chr->frozen() ) { private_say_above( client->chr, client->chr, "I am frozen and cannot do that." ); return; } if ( !id.can_use_while_paralyzed && client->chr->paralyzed() ) { private_say_above( client->chr, client->chr, "I am paralyzed and cannot do that." ); return; } unsigned short dst = pol_distance( client->chr, item ); if ( dst > id.doubleclick_range && !client->chr->can_dblclickany() ) { private_say_above( client->chr, item, "That is too far away." ); return; } UObject* obj = item->toplevel_owner(); obj = obj->self_as_owner(); if ( id.use_requires_los && !client->chr->realm->has_los( *client->chr, *obj ) ) // DAVE // 11/24 { private_say_above( client->chr, item, "I can't see that." ); return; } ScriptDef sd; sd.quickconfig( "scripts/misc/dblclickitem.ecl" ); if ( sd.exists() ) { ref_ptr<Bscript::EScriptProgram> prog; prog = find_script2( sd, false, Plib::systemstate.config.cache_interactive_scripts ); if ( prog.get() != nullptr ) client->chr->start_script( prog.get(), false, new Module::EItemRefObjImp( item ) ); } item->double_click( client ); return; } // allow looking into containers being traded if ( client->chr->is_trading() ) { UContainer* cont = client->chr->trade_container()->find_container( serial ); if ( cont != nullptr ) { cont->builtin_on_use( client ); if ( !cont->locked() ) { if ( client->chr->trading_with->client != nullptr ) cont->builtin_on_use( client->chr->trading_with->client ); } return; } } } }
void equip_item( Client *client, PKTIN_13 *msg ) { u32 serial = cfBEu32( msg->serial ); u8 layer = msg->layer; u32 equip_on_serial = cfBEu32( msg->equipped_on ); if ((layer > HIGHEST_LAYER) || (layer == 0) || client->chr->dead()) { send_item_move_failure( client, MOVE_ITEM_FAILURE_ILLEGAL_EQUIP ); return; } Item *item = client->chr->gotten_item; if (item == NULL) { Log( "Character %08lX tried to equip item %08lx, which did not exist in gotten_items.\n", client->chr->serial, serial ); send_item_move_failure( client, MOVE_ITEM_FAILURE_ILLEGAL_EQUIP ); // 5 return; } if (item->serial != serial) { Log( "Character %08lX tried to equip item %08lx, but had gotten item %08lX\n", client->chr->serial, serial, item->serial); send_item_move_failure( client, MOVE_ITEM_FAILURE_ILLEGAL_EQUIP ); // 5 item->gotten_by = NULL; return; } ItemRef itemref(item); item->layer = item->tile_layer; client->chr->gotten_item->inuse(false); item->is_gotten(false); item->gotten_by = NULL; client->chr->gotten_item = NULL; Character* equip_on = NULL; if (equip_on_serial == client->chr->serial) { equip_on = client->chr; } else { equip_on = find_character( equip_on_serial ); if (equip_on == NULL || !client->chr->can_clothe( equip_on )) { send_item_move_failure( client, MOVE_ITEM_FAILURE_ILLEGAL_EQUIP ); undo_get_item( client->chr, item ); return; } } if (equip_on->layer_is_equipped( item->tile_layer )) { // it appears the client already checks for this, so this code hasn't been exercised. // we'll assume client mouse holds on to object // 3D Client doesn't check for this! send_item_move_failure( client, MOVE_ITEM_FAILURE_ALREADY_WORN ); undo_get_item( client->chr, item ); //added 11/01/03 for 3d client return; } if (!equip_on->strong_enough_to_equip( item )) { send_item_move_failure( client, MOVE_ITEM_FAILURE_ILLEGAL_EQUIP ); // the client now puts the item back where it was before. // return the item to wherever it was. (?) undo_get_item( client->chr, item ); if (client->chr == equip_on) { send_sysmessage( client, "You are not strong enough to use that." ); } else { send_sysmessage( client, "Insufficient strength to equip that." ); } return; } if (!equip_on->equippable( item ) || !item->check_equiptest_scripts( equip_on ) || !item->check_equip_script( equip_on, false )) { send_item_move_failure( client, MOVE_ITEM_FAILURE_ILLEGAL_EQUIP ); if(item->orphan()) { return; } undo_get_item( client->chr, item ); return; } if(item->orphan()) { return; } equip_on->equip( item ); send_wornitem_to_inrange( equip_on, item ); }
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 ); } }