void serializeto(const Costume &costume,BitStream &bs,const ColorAndPartPacker *packer) { bs.StorePackedBits(3,costume.m_body_type); // 0:male normal bs.StoreBits(32,costume.skin_color); // rgb ? bs.StoreFloat(costume.m_height); bs.StoreFloat(costume.m_physique); bs.StoreBits(1,costume.m_send_full_costume); //m_num_parts = m_parts.size(); assert(!costume.m_parts.empty()); bs.StorePackedBits(4,costume.m_parts.size()); try { for(uint32_t costume_part=0; costume_part<costume.m_parts.size();costume_part++) { CostumePart part=costume.m_parts[costume_part]; // TODO: this is bad code, it's purpose is to NOT send all part strings if m_non_default_costme_p is false part.m_full_part = costume.m_send_full_costume; ::serializeto(part,bs,packer); } } catch(cereal::RapidJSONException &e) { qWarning() << e.what(); } catch(std::exception &e) { qCritical() << e.what(); } }
void serializeLevelsStats(const Character &src,BitStream &bs, bool /*sendAbsolute*/) { bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,0); bs.StorePackedBits(4,getLevel(src)); bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,1); bs.StorePackedBits(4,getCombatLevel(src)); bs.StoreBits(1,0); // no more data }
void serializeFullStats(const Parse_CharAttrib &src,BitStream &bs, bool /*sendAbsolute*/) { bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,0); bs.StorePackedBits(7,src.m_HitPoints); bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,1); bs.StorePackedBits(7,src.m_Endurance); bs.StoreBits(1,0); // no more data }
void EntitiesResponse::sendClientData(BitStream &tgt) const { PlayerEntity *ent=static_cast<PlayerEntity *>(m_client->char_entity()); Character &player_char=ent->m_char; if(!m_incremental) { ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("\tSending Character to client: full\n"))); //full_update - > receiveCharacterFromServer // initial character update = level/name/class/origin/map_name //m_client->char_entity()->m_char.m_ent=m_client->char_entity(); ent->serialize_full(tgt); player_char.sendTray(tgt); player_char.sendTrayMode(tgt); tgt.StoreString(ent->name()); // maxlength 32 tgt.StoreString(ent->m_battle_cry); //max 128 tgt.StoreString(ent->m_character_description); //max 1024 player_char.sendWindows(tgt); tgt.StoreBits(1,0); // lfg related tgt.StoreBits(1,0); // a2->ent_player2->field_AC player_char.sendTeamBuffMode(tgt); player_char.sendDockMode(tgt); player_char.sendChatSettings(tgt); player_char.sendTitles(tgt); player_char.sendDescription(tgt); uint8_t auth_data[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; tgt.StoreBitArray(auth_data,128); player_char.sendKeybinds(tgt); player_char.sendOptions(tgt); player_char.sendFriendList(tgt); } else { //ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("\tSending Character to client: stats-only\n"))); ent->m_char.sendFullStats(tgt); } storePowerInfoUpdate(tgt); //storePowerModeUpdate(tgt); //storeBadgeUpdate(tgt); //storeGenericinventoryUpdate(tgt); //storeInventionUpdate(tgt); storeTeamList(tgt); storeSuperStats(tgt); storeGroupDyn(tgt); bool additional=false; tgt.StoreBits(1,additional); if(additional) { tgt.StoreFloat(0.1f); tgt.StoreFloat(0.2f); // camera_yaw tgt.StoreFloat(0.3f); } }
void EntityManager::sendGlobalEntDebugInfo( BitStream &tgt ) const { tgt.StoreBits(1,0); // nothing here for now // first while loop here tgt.StoreBits(1,0); // second while loop here tgt.StoreBits(1,0); // if here // players in zone and such tgt.StoreBits(1,0); // third while loop here }
void EntitiesResponse::storeTeamList(BitStream &bs) const { int team_id=0; // NetStructure::storePackedBitsConditional(bs,20,team_id); //storePackedBitsConditional(bs,20,0); bs.StoreBits(1,0); bs.StoreBits(1,0); if(team_id>0) { bs.StoreBits(32,0); int num_members=0; bs.StorePackedBits(1,num_members); } }
void Character::sendOwnedPowers(BitStream &bs) const { bs.StorePackedBits(4, m_char_data.m_powersets.size()); // count for(const CharacterPowerSet &pset : m_char_data.m_powersets) { bs.StorePackedBits(5, pset.m_level_bought); bs.StorePackedBits(4, pset.m_powers.size()); for(const CharacterPower &power : pset.m_powers) { power.m_power_info.serializeto(bs); bs.StorePackedBits(5, power.m_level_bought); bs.StoreFloat(power.getPowerTemplate().Range); if(power.m_total_eh_slots > power.m_enhancements.size()) qCWarning(logPowers) << "sendOwnedPowers: Total EH Slots larger than vector!"; bs.StorePackedBits(4, power.m_enhancements.size()); for(const CharacterEnhancement &eh : power.m_enhancements) { bs.StoreBits(1, eh.m_slot_used); // slot has enhancement if(eh.m_slot_used) { eh.m_enhance_info.serializeto(bs); bs.StorePackedBits(5, eh.m_level); bs.StorePackedBits(2, eh.m_num_combines); } } } } }
void EntityManager::sendEntities( BitStream &tgt ) const { Entity *pEnt = NULL; std::list<Entity *>::const_iterator iter = m_entlist.begin(); int last_idx; int delta;// sending delta between entities idxs -> assert(m_entlist.size()>0 && "Attempting to send empty entity list, the client will hang!"); if(iter!=m_entlist.end()) { pEnt = *iter; tgt.StorePackedBits(1,pEnt->getIdx()); last_idx = pEnt->getIdx(); pEnt->serializeto(tgt); iter++; } while(iter!=m_entlist.end()) { //assert(!"Only one for now"); pEnt = *iter; delta = pEnt->getIdx()-last_idx -1; tgt.StorePackedBits(1,delta); last_idx = pEnt->getIdx(); pEnt->serializeto(tgt); iter++; } // last entity marker tgt.StorePackedBits(1,0); // next ent tgt.StoreBits(1,1); // create/update -> create tgt.StoreBits(1,1); // empty entity. will finish the receiving loop }
void serializeStats(const Character &src,BitStream &bs, bool sendAbsolute) { // Send CurrentAttribs // Send MaxAttribs // Send levels uint32_t field_idx=0; bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,field_idx++); // CurrentAttribs serializeStats(src.m_char_data.m_current_attribs,bs,sendAbsolute); bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,field_idx++); // MaxAttribs serializeStats(src.m_max_attribs,bs,sendAbsolute); bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,field_idx++); // levels serializeLevelsStats(src,bs,sendAbsolute); bs.StoreBits(1,0); // we have no more data }
void NetStructure::storeCached_Color( BitStream &bs,uint32_t col ) { uint32_t cache_idx=0; uint32_t prev_val=0; if(col && WorldData::instance()->colors().find_index(col,cache_idx,prev_val,false)) { cache_idx+=1; } bs.StoreBits(1,(cache_idx||col==0)); if(cache_idx||col==0) { bs.StorePackedBits(colorcachecount_bitlength,cache_idx); } else { bs.StoreBits(32,col); } }
void EntitiesResponse::storePowerInfoUpdate(BitStream &bs) const { bool powerinfo_available=false; bs.StoreBits(1,powerinfo_available); if ( powerinfo_available ) { bs.StoreBits(1,false); bs.StorePackedBits(1,0); // send powers bs.StoreBits(1,0); bs.StorePackedBits(4,0); bs.StorePackedBits(1,0); // ... missing } // send powers bs.StoreBits(1,0); }
void UpdateServer::serializeto( BitStream &tgt ) const { tgt.StorePackedBits(1, 2); //opcode tgt.StorePackedBits(1, m_build_date); tgt.StorePackedBits(1, 0); // flags tgt.StoreString(currentVersion); tgt.StoreBitArray(clientInfo,sizeof(clientInfo)*8); tgt.StorePackedBits(1, authID); tgt.StoreBits(32, authCookie); tgt.StoreString(accountName); }
void EntitiesResponse::storePowerModeUpdate(BitStream &bs) const { bs.StoreBits(1,0); if(false) { bs.StorePackedBits(3,1); for(int i=0; i<1; i++) { bs.StorePackedBits(3,0); } } }
void Character::serialize_costumes(BitStream &bs, const ColorAndPartPacker *packer , bool send_all_costumes) const { if(send_all_costumes) // This is only sent to the current player { bs.StoreBits(1, m_add_new_costume); if(m_add_new_costume) { bs.StoreBits(32, getCurrentCostumeIdx(*this)); bs.StoreBits(32, uint32_t(m_costumes.size())-1); // must be minus 1 because the client adds 1 } bool multiple_costumes = m_costumes.size() > 1; bs.StoreBits(1, multiple_costumes); if(multiple_costumes) { for(const Costume & c : m_costumes) ::serializeto(c,bs,packer); } else ::serializeto(m_costumes[getCurrentCostumeIdx(*this)],bs,packer); bs.StoreBits(1, m_char_data.m_has_sg_costume); if(m_char_data.m_has_sg_costume) { ::serializeto(*m_sg_costume,bs,packer); bs.StoreBits(1, m_char_data.m_using_sg_costume); } } else // other player's costumes we're sending only their current. ::serializeto(*getCurrentCostume(),bs,packer); }
void storeTransformMatrix( BitStream &tgt,const TransformStruct &src ) { tgt.StoreBits(1,1); // partial tgt.StoreBits(1,src.v1_set ? 1:0); tgt.StoreBits(1,src.v2_set ? 1:0); tgt.StoreBits(1,src.v3_set ? 1:0); if(src.v1_set) { for(int i=0; i<3; i++) storeFloatPacked(tgt,src.v1[i]); } if(src.v2_set) { for(int i=0; i<3; i++) storeFloatPacked(tgt,src.v2[i]); } if(src.v3_set) { for(int i=0; i<3; i++) storeFloatPacked(tgt,src.v3[i]); } }
void Character::sendFriendList(BitStream &bs) const { const FriendsList *fl(&m_char_data.m_friendlist); bs.StorePackedBits(1,1); // v2 = force_update bs.StorePackedBits(1,fl->m_friends_count); for(int i=0; i<fl->m_friends_count; ++i) { bs.StoreBits(1,fl->m_has_friends); // if false, client will skip this iteration bs.StorePackedBits(1,fl->m_friends[i].m_db_id); bs.StoreBits(1,fl->m_friends[i].m_online_status); bs.StoreString(fl->m_friends[i].m_name); bs.StorePackedBits(1,fl->m_friends[i].m_class_idx); bs.StorePackedBits(1,fl->m_friends[i].m_origin_idx); if(!fl->m_friends[i].m_online_status) continue; // if friend is offline, the rest is skipped bs.StorePackedBits(1,fl->m_friends[i].m_map_idx); bs.StoreString(fl->m_friends[i].m_mapname); } }
void EntitiesResponse::sendServerPhysicsPositions(BitStream &bs) const { Entity * target = m_client->char_entity(); bool full_update = true; bool has_control_id = true; bs.StoreBits(1,full_update); if( !full_update ) bs.StoreBits(1,has_control_id); fprintf(stderr,"Phys: send %d ",target->m_input_ack); if( full_update || has_control_id) bs.StoreBits(16,target->m_input_ack); //target->m_input_ack if(full_update) { bs.StoreFloat(target->pos.x); // server position bs.StoreFloat(target->pos.y); bs.StoreFloat(target->pos.z); NetStructure::storeFloatConditional(bs,0.0f); // PYR rotation ? NetStructure::storeFloatConditional(bs,0.0f); NetStructure::storeFloatConditional(bs,0.0f); } }
void EntitiesResponse::sendServerControlState(BitStream &bs) const { Vector3 spd(1,80,1); Vector3 zeroes; bool m_flying=false; bool m_dazed=false; // user entity Entity *ent = m_client->char_entity(); CscCommon_Sub28 struct_csc; memset(&struct_csc,0,sizeof(struct_csc)); static int vla=1; int g=rand()&0xff; for(int i=0; i<3; ++i) struct_csc.a.v[i] = g+vla; vla+=1; struct_csc.b.max_speed = struct_csc.a.max_speed = 5.0f; struct_csc.b.gravitational_constant = struct_csc.a.gravitational_constant = 3.0f; // for(int i=3; i<5; ++i) // struct_csc.a.v[i] = rand()&0xf; bool update_part_1=true; bool update_part_2=false; bs.StoreBits(1,update_part_1); if(update_part_1) { //rand()&0xFF bs.StoreBits(8,vla); // value stored in control state field_134 // after input_send_time_initialized, this value is enqueued as CSC_9's control_flags // This is entity speed vector !! NetStructure::storeVector(bs,spd); bs.StoreFloat(1.0f); // speed rel back bs.StoreBitArray((uint8_t *)&struct_csc,sizeof(CscCommon_Sub28)*8); bs.StoreFloat(0.1f); bs.StoreBits(1,m_flying); // key push bits ?? bs.StoreBits(1,m_dazed); // key push bits ?? bs.StoreBits(1,0); // key push bits ?? bs.StoreBits(1,0); // key push bits ?? bs.StoreBits(1,0); // key push bits ?? bs.StoreBits(1,0); // key push bits ?? } // Used to force the client to a position/speed/pitch/rotation by server bs.StoreBits(1,update_part_2); if(update_part_2) { bs.StorePackedBits(1,0); // sets g_client_pos_id_rel NetStructure::storeVector(bs,spd); NetStructure::storeVectorConditional(bs,zeroes); // vector3 -> speed ? likely NetStructure::storeFloatConditional(bs,0); // Pitch not used ? NetStructure::storeFloatConditional(bs,ent->inp_state.pyr.x); // Pitch NetStructure::storeFloatConditional(bs,0); // Roll bs.StorePackedBits(1,0); // sets the lowest bit in CscCommon::flags } }
void NetStructure::storeCached_String( BitStream &bs,const std::string & str ) { uint32_t cache_idx=0; uint32_t prev_val=0; if(str.size() && WorldData::instance()->strings().find_index(str,cache_idx,prev_val,false)) { cache_idx+=1; } bs.StoreBits(1,(cache_idx||str.size()==0)); if(cache_idx||str.size()==0) bs.StorePackedBits(stringcachecount_bitlength,cache_idx); else bs.StoreString(str); }
void Character::sendEnhancements(BitStream &bs) const { bs.StorePackedBits(5, m_char_data.m_enhancements.size()); // count for(size_t i = 0; i < m_char_data.m_enhancements.size(); ++i) { bs.StorePackedBits(3, m_char_data.m_enhancements[i].m_slot_idx); // boost idx, maybe use m_enhancement_idx bs.StoreBits(1, m_char_data.m_enhancements[i].m_slot_used); // 1 set, 0 clear if(m_char_data.m_enhancements[i].m_slot_used) { m_char_data.m_enhancements[i].m_enhance_info.serializeto(bs); bs.StorePackedBits(5, m_char_data.m_enhancements[i].m_level); // boost idx bs.StorePackedBits(2, m_char_data.m_enhancements[i].m_num_combines); // boost idx } } }
void EntitiesResponse::serializeto_internal( BitStream &tgt ) const { EntityManager &ent_manager=m_client->current_map()->m_entities; tgt.StorePackedBits(1,m_incremental ? 2 : 3); // opcode 3 - full update. tgt.StoreBits(1,entReceiveUpdate); // passed to Entity::EntReceive as a parameter sendCommands(tgt); tgt.StoreBits(32,abs_time); //tgt.StoreBits(32,db_time); tgt.StoreBits(1,unkn2); if(unkn2) { //g_debug_info 0 //interpolation level 2 //g_bitcount_rel 1 } else { tgt.StoreBits(1,debug_info); tgt.StoreBits(1,m_interpolating); if(m_interpolating==1) { tgt.StoreBits(2,m_interpolation_level); tgt.StoreBits(2,m_interpolation_bits); } } //else debug_info = false; ent_manager.sendEntities(tgt); if(debug_info&&!unkn2) { ent_manager.sendDebuggedEntities(tgt); // while loop, sending entity id's and debug info for each ent_manager.sendGlobalEntDebugInfo(tgt); } sendServerPhysicsPositions(tgt); // These are not client specific ? sendControlState(tgt);// These are not client specific ? ent_manager.sendDeletes(tgt); // Client specific part sendClientData(tgt); //FIXME: Most Server messages must follow entity update. }
void Character::sendInspirations(BitStream &bs) const { int max_cols = m_char_data.m_max_insp_cols; int max_rows = m_char_data.m_max_insp_rows; bs.StorePackedBits(3, max_cols); // count bs.StorePackedBits(3, max_rows); // count for(int col = 0; col < max_cols; ++col) { for(int row = 0; row < max_rows; ++row) { bs.StoreBits(1, m_char_data.m_inspirations.value(col, row).m_has_insp); if(m_char_data.m_inspirations.value(col, row).m_has_insp) m_char_data.m_inspirations.value(col, row).m_insp_info.serializeto(bs); } } }
void Character::sendTitles(BitStream &bs, NameFlag hasname, ConditionalFlag conditional) const { if(hasname == NameFlag::HasName) bs.StoreString(getName()); bs.StoreBits(1, m_char_data.m_has_the_prefix); // an index to a title prefix ( 0 - None; 1 - The ) if(conditional) { storeStringConditional(bs, m_char_data.m_titles[0]); // Title 1 - generic title (first) storeStringConditional(bs, m_char_data.m_titles[1]); // Title 2 - origin title (second) storeStringConditional(bs, m_char_data.m_titles[2]); // Title 3 - yellow title (special) } else { bs.StoreString(m_char_data.m_titles[0]); // Title 1 - generic title (first) bs.StoreString(m_char_data.m_titles[1]); // Title 2 - origin title (second) bs.StoreString(m_char_data.m_titles[2]); // Title 3 - yellow title (special) } }
void serializeFullStats(const Character &src,BitStream &bs, bool sendAbsolute) { uint32_t field_idx=0; bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,field_idx++); // first field is CurrentAttribs serializeFullStats(src.m_char_data.m_current_attribs,bs,sendAbsolute); bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,field_idx++); // first field is MaxAttribs serializeFullStats(src.m_max_attribs,bs,sendAbsolute); bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,field_idx++); // levels serializeLevelsStats(src,bs,sendAbsolute); bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,field_idx++); // ExperiencePoints bs.StorePackedBits(16,getXP(src)); bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,field_idx++); // ExperienceDebt bs.StorePackedBits(16,getDebt(src)); bs.StoreBits(1,1); // we have more data bs.StorePackedBits(1,field_idx++); // Influence bs.StorePackedBits(16,getInf(src)); bs.StoreBits(1,0); // we have no more data }
void storePackedBitsConditional( BitStream &bs,uint8_t numbits,int bits ) { bs.StoreBits(1,bits!=0); if(bits) bs.StorePackedBits(numbits,bits); }
void storeTransformMatrix(BitStream &tgt, const glm::mat4x3 &src ) { tgt.StoreBits(1,0); // no packed matrices for now tgt.StoreBitArray((const uint8_t*)glm::value_ptr(src),12*4*8); }
void storeStringConditional( BitStream &bs,const QString &str ) { bs.StoreBits(1,str.size()>0); if(str.size()>0) bs.StoreString(str); }
void storeFloatPacked( BitStream &bs,float val ) { bs.StoreBits(1,0); bs.StoreFloat(val); }
void storeFloatConditional( BitStream &bs,float val ) { bs.StoreBits(1,val!=0.0f); if(val!=0.0f) bs.StoreFloat(val); }
void NetStructure::storeTransformMatrix( BitStream &tgt,const Matrix4x3 &src ) { tgt.StoreBits(1,0); // no packed matrices for now tgt.StoreBitArray((uint8_t*)&src,12*4*8); }