bool send_tip( Client* client, const char* tipname, unsigned short tipnum ) { ifstream ifs( tipname ); ifs.read( tipmsg.text, sizeof tipmsg.text ); streamsize textlen = ifs.gcount(); if ( textlen > 0 && unsigned(textlen) <= sizeof tipmsg.text) { u16 msglen = static_cast<u16>(offsetof(PKTOUT_A6, text) + textlen); tipmsg.msgtype = PKTOUT_A6_ID; tipmsg.msglen = ctBEu16(msglen); tipmsg.type = PKTOUT_A6::TYPE_TIP; tipmsg.unk4 = 0; tipmsg.unk5 = 0; tipmsg.tipnum = ctBEu16(tipnum); tipmsg.textlen = ctBEu16(textlen); // tipmsg.text read in above transmit( client, &tipmsg, msglen ); return true; } else { return false; } }
void UDoor::toggle() { const DoorDesc& dd = fast_find_doordesc( objtype_ ); unsigned short oldx = x, oldy = y; set_dirty(); if (is_open()) { if (dd.graphic) graphic = dd.graphic; else graphic = static_cast<u16>(objtype_); x -= dd.xmod; y -= dd.ymod; } else { graphic = dd.open_graphic; x += dd.xmod; y += dd.ymod; } MoveItemWorldPosition( oldx, oldy, this, NULL ); graphic_ext = ctBEu16( graphic ); send_item_to_inrange( this ); }
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; } }
SOCKET open_listen_socket( unsigned short port ) { int res; SOCKET sck; sck = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if (sck < 0) { throw runtime_error( "Unable to create listening socket" ); return -1; } apply_socket_options( sck ); #ifndef WIN32 int reuse_opt = 1; res = setsockopt( sck, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse_opt, sizeof(reuse_opt) ); if (res < 0) { throw runtime_error( "Unable to setsockopt (SO_REUSEADDR) on listening socket, res = " + decint(res) ); } #endif #define DISABLE_NAGLE_ALGORITHM 0 #if DISABLE_NAGLE_ALGORITHM int tcp_nodelay = -1; res = setsockopt( sck, IPPROTO_TCP, TCP_NODELAY, (const char *) &tcp_nodelay, sizeof(tcp_nodelay) ); if (res < 0) { cout << "Unable to setsockopt (TCP_NODELAY) on listening socket, res=" << res << endl; return -1; } #endif struct sockaddr_in connection; connection.sin_family = AF_INET; connection.sin_addr.s_addr = INADDR_ANY; connection.sin_port = ctBEu16( port ); res = bind( sck, (struct sockaddr *) &connection, sizeof connection ); if ( res < 0 ) { // Aug. 16, 2006. Austin // Added the port number that failed. string tmp_error = "Unable to bind listening socket. Port("+decint(port)+") Res="+decint(res); throw runtime_error(tmp_error); } res = listen( sck, SOMAXCONN ); if (res < 0) { throw runtime_error( "Listen failed, res=" + decint(res) ); } return sck; }
void send_tip( Client* client, const std::string& tiptext ) { unsigned textlen = tiptext.size(); if (textlen >= sizeof tipmsg.text) textlen = sizeof tipmsg.text - 1; int msglen = offsetof(PKTOUT_A6, text) + textlen; tipmsg.msgtype = PKTOUT_A6_ID; tipmsg.msglen = ctBEu16(msglen); tipmsg.type = PKTOUT_A6::TYPE_TIP; tipmsg.unk4 = 0; tipmsg.unk5 = 0; tipmsg.tipnum = 0; tipmsg.textlen = ctBEu16(textlen); memcpy( tipmsg.text, tiptext.c_str(), textlen ); tipmsg.text[textlen] = '\0'; transmit( client, &tipmsg, msglen ); }
void send_stat_locks (Client *client, Character *chr) { if (client->getversiondetail().major < 3) // only in AOS, I think return; u8 lockbit = 0; lockbit |= chr->attribute(uoclient_general.strength.id).lock() << 4; //XX SS DD II (2 bits for each lock) lockbit |= chr->attribute(uoclient_general.dexterity.id).lock() << 2; lockbit |= chr->attribute(uoclient_general.intelligence.id).lock(); PKTBI_BF msg; msg.msgtype = PKTBI_BF_ID; msg.msglen = ctBEu16(12); msg.subcmd = ctBEu16(PKTBI_BF::TYPE_EXTENDED_STATS_OUT); msg.extstatsout.type = 0x02; // 2D Client = 0x02, KR = 0x05 msg.extstatsout.serial = chr->serial_ext; msg.extstatsout.unk = 0; msg.extstatsout.lockbits = lockbit; client->transmit(&msg, 12); }
void send_short_statmsg( Client *client, Character *chr ) { unsigned short msglen = offsetof( PKTOUT_11_V1, gender ); PKTOUT_11_V1 msg; msg.msgtype = PKTOUT_11_V1_ID; msg.msglen = ctBEu16(msglen); msg.serial = chr->serial_ext; strzcpy( msg.name, chr->name().c_str(), sizeof msg.name ); if (uoclient_general.hits.any) { long h, mh; h = chr->vital(uoclient_general.hits.id).current_ones(); if (h > 0xFFFF) h = 0xFFFF; //msg.hits = ctBEu16( static_cast<u16>(h) ); mh = chr->vital(uoclient_general.hits.id).maximum_ones(); if (mh > 0xFFFF) mh = 0xFFFF; //msg.max_hits = ctBEu16( static_cast<u16>(mh) ); msg.hits = ctBEu16( static_cast<u16>(h * 1000 / mh) ); msg.max_hits = ctBEu16( 1000 ); } else { msg.hits = 0; msg.max_hits = 0; } msg.renameable = (client->chr->can_rename( chr ) ? 0xFF : 0); msg.moreinfo = 0; transmit(client, &msg, msglen ); }
void send_update_hits_to_inrange( Character *chr ) { PKTOUT_A1 msg; msg.msgtype = PKTOUT_A1_ID; msg.serial = chr->serial_ext; if (uoclient_general.hits.any) { long h = chr->vital(uoclient_general.hits.id).current_ones(); if (h > 0xFFFF) h = 0xFFFF; msg.hits = ctBEu16( static_cast<u16>(h) ); long mh = chr->vital(uoclient_general.hits.id).maximum_ones(); if (mh > 0xFFFF) mh = 0xFFFF; msg.max_hits = ctBEu16( static_cast<u16>(mh) ); // Send proper data to self (if we exist?) if (chr->client && chr->client->ready) transmit( chr->client, &msg, sizeof msg ); // To stop "HP snooping"... msg.hits = ctBEu16( static_cast<u16>(h * 1000 / mh) ); msg.max_hits = ctBEu16( 1000 ); } else { msg.hits = 0; msg.max_hits = 0; if (chr->client && chr->client->ready) transmit( chr->client, &msg, sizeof msg ); } // Exclude self... otherwise their status-window shows 1000 hp!! >_< transmit_to_others_inrange( chr, &msg, sizeof msg, false, false ); }
// Warning: Make sure that your buffer if large enough! Don't forget to add space for null terminator if requested. bool convertArrayToUC( Bscript::ObjArray*& in_text, u16* out_wtext, size_t textlen, bool ConvToBE /*false*/, bool nullterm /*true*/ ) { u16 value; size_t pos = 0; for( size_t i = 0; i < textlen; i++ ) { Bscript::BObject* bo = in_text->ref_arr[i].get( ); if( bo == NULL ) continue; if ( !bo->isa( Bscript::BObjectImp::OTLong ) ) return false; Bscript::BObjectImp *imp = bo->impptr( ); Bscript::BLong* blong = static_cast<Bscript::BLong*>( imp ); value = (u16)( blong->value() & 0xFFFF ); out_wtext[pos++] = ConvToBE ? ctBEu16( value ) : value; // Jump out on a NULL (EOS) value (should stop exploits, too?) if( value == 0L ) return true; } if( nullterm ) out_wtext[pos] = (u16)0L; return true; }
// 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) ); }
Item* Item::create( const ItemDesc& id, u32 serial) { unsigned short objtype = id.objtype; unsigned short graphic = id.graphic; Item* item; // FIXME looks like a place for a bunch of function pointers if I ever saw one. if (id.type == ItemDesc::DOORDESC) { item = new UDoor( static_cast<const DoorDesc&>(id) ); } else if (id.type == ItemDesc::BOATDESC) { // still created with create_multi return NULL; } else if (id.type == ItemDesc::HOUSEDESC) { // still created with create_multi return NULL; } else if ( (objtype >= spell_scroll_objtype_limits[0][0] && objtype <= spell_scroll_objtype_limits[0][1]) || (objtype >= spell_scroll_objtype_limits[1][0] && objtype <= spell_scroll_objtype_limits[1][1]) || (objtype >= spell_scroll_objtype_limits[2][0] && objtype <= spell_scroll_objtype_limits[2][1]) ) { item = new USpellScroll( id ); } else if (objtype == UOBJ_CORPSE) // ITEMDESCTODO make new ItemDesc type { item = new UCorpse( static_cast<const ContainerDesc&>(id) ); } else if (id.type == ItemDesc::SPELLBOOKDESC) // ITEMDESCTODO make new ItemDesc type { item = new Spellbook( static_cast<const SpellbookDesc&>(id) ); } else if (id.type == ItemDesc::CONTAINERDESC) { item = new UContainer( static_cast<const ContainerDesc&>(id) ); } else if (id.type == ItemDesc::WEAPONDESC) { // we call find_itemdesc here because the item descriptor passed in may not // be the "real" one - it may be a temporary descriptor. const WeaponDesc* permanent_descriptor = static_cast<const WeaponDesc*>(&find_itemdesc(objtype)); item = new UWeapon( static_cast<const WeaponDesc&>(id), permanent_descriptor ); } else if (id.type == ItemDesc::ARMORDESC) { const ArmorDesc* permanent_descriptor = static_cast<const ArmorDesc*>(&find_itemdesc(objtype)); item = new UArmor( static_cast<const ArmorDesc&>(id), permanent_descriptor ); } else if (id.type == ItemDesc::MAPDESC) // (graphic >= UOBJ_MAP1 && graphic <= UOBJ_ROLLED_MAP2) { item = new Map( static_cast<const MapDesc&>(id) ); } else if (objtype == EXTOBJ_PORT_PLANK || objtype == EXTOBJ_STARBOARD_PLANK)// ITEMDESCTODO make new ItemDesc type { item = new UPlank( id ); } else if (objtype_is_lockable(objtype)) { item = new ULockable( id, CLASS_ITEM ); } else { item = new Item( id, CLASS_ITEM ); } // 12-17-2008 MuadDib added for reading the tilelayer at all times while retaining item.layer useage. item->tile_layer = tilelayer( graphic ); // Have to be set after the item is created, because item graphic changes // Because items can have facing 0 as the lightsource we use as default 127 to check if ( item->facing == 127 ) item->facing = item->tile_layer; if (serial) { item->serial = UseItemSerialNumber(serial); item->clear_dirty(); } else if (dont_save_itemtype[objtype]) { item->set_dirty(); item->serial = GetNewItemSerialNumber(); } else // creating something new { item->set_dirty(); remove_resources( objtype, 1 ); item->serial = GetNewItemSerialNumber(); } ////HASH objecthash.Insert(item); //// item->serial_ext = ctBEu32( item->serial ); item->restart_decay_timer(); item->graphic = graphic; item->graphic_ext = ctBEu16( item->graphic ); item->copyprops( id.props ); #ifdef PERGON string value_self; if (!item->getprop( "ct", value_self )) // Pergon: Check if Prop still exist - prevents Overwrite on Server-Restart item->setprop("ct", "i" + decint( read_gameclock() )); // Pergon: Init Property CreateTime for a new Item #endif if (!id.control_script.empty()) { UOExecutorModule* uoemod = start_script( id.control_script, item->make_ref() ); if (!uoemod) { Log( "Unable to start control script %s for %s\n", id.control_script.name().c_str(), id.objtype_description().c_str() ); } } for( unsigned element = 0; element <= ELEMENTAL_TYPE_MAX; ++element ) { switch(element) { case ELEMENTAL_FIRE: item->element_resist.fire = id.element_resist.fire; item->element_damage.fire = id.element_damage.fire;break; case ELEMENTAL_COLD: item->element_resist.cold = id.element_resist.cold; item->element_damage.cold = id.element_damage.cold;break; case ELEMENTAL_ENERGY: item->element_resist.energy = id.element_resist.energy; item->element_damage.energy = id.element_damage.energy; break; case ELEMENTAL_POISON: item->element_resist.poison = id.element_resist.poison; item->element_damage.poison = id.element_damage.poison; break; case ELEMENTAL_PHYSICAL: item->element_resist.physical = id.element_resist.physical; item->element_damage.physical = id.element_damage.physical; break; } } // if ItemDesc is a dynamic one desc could differ and would be lost const ItemDesc& origid = find_itemdesc( item->objtype_ ); if (id.desc != origid.desc) item->setname( id.desc); return item; }