//===========================================================================// // File: NetAutoPacketSpliter.cpp //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 01/06/1999 JSE Inital coding //---------------------------------------------------------------------------// // Copyright (C) 1998, Microsoft Corp. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "MW4Headers.hpp" #include "MWEntityManager.hpp" #include "NetUpdateManager.hpp" #include "Dictionary.hpp" #include "NetAutoPacketSpliter.hpp" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetUpdateSortEntry::NetUpdateSortEntry(Entity *entity, int size, int type, UpdateRate rate): Plug(DefaultData), m_rate(rate) { m_entity = entity; m_size = size; m_type = type; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetUpdatePageHolder::NetUpdatePageHolder(int page_overhead): Plug(DefaultData), m_UpdateEntries(NULL) { entryCount = 0; totalMaxSize = page_overhead; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetUpdatePageHolder::~NetUpdatePageHolder() { m_UpdateEntries.DeletePlugs(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void NetUpdatePageHolder::AddToList(NetUpdateSortEntry *entry, int paragraph_overhead) { ++entryCount; totalMaxSize += entry->m_size + paragraph_overhead; m_UpdateEntries.Add(entry); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool NetUpdatePageHolder::IsThereRoom(NetUpdateSortEntry *entry, int paragraph_overhead) { //if (entryCount+1 >= 64) // return false; if (totalMaxSize + entry->m_size + paragraph_overhead < (Network::DefaultPacketSize*8)) return true; return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #ifdef LAB_ONLY char* Text_Table[DictionaryPage::UpdateCycleCount] = { "HalfhzType", "OneHzType", "TwoHzType", "ThreeHzType", "FourHzType", "SixHzType", "EightHzType", "NineHzType", "TwelveHzType", "SixteenHzType" }; char* Update_Text_Table[UpdateManager::UpdateCount] = { "MechPositionUpdateID", "MechAnimationUpdateID", "MechMovemntUpdateID", "MechExternalDamageUpdateID", "MechFirstPersonPositionUpdateID", "MechFirstPersonControlUpdateID", "WeaponCommandID", "MissionObjectiveUpdateID", "MechInternalDamageUpdateID", "MechInternalHeatUpdateID", "SubsystemUpdateID", "FlushUpdateID", "SearchLightUpdateID", "InternalAMSAmmoUpdateID", "ExternalAMSAmmoUpdateID", "NearBuildingExternalDamageUpdateID", "SecondaryBuildingExternalDamageUpdateID", "FarBuildingExternalDamageUpdateID", "ExternalJumpJetUpdateID", "InternalJumpJetUpdateID", "VehicleDamageUpdateID", "AirMovementUpdateID", "GroundMovementUpdateID", "TurretMovementUpdateID", "TorsoMovementUpdateID", "NavPointUpdateID", "FlagUpdateID", "TimeUpdateID", "SecurityQueryID", "SecurityResponseID", "PingUpdateID" }; #endif void NetUpdatePageHolder::AddSelfToDictionary(Dictionary *dictionary, int page_number) { DictionaryPage *page = dictionary->MakeDictionaryPage(page_number); //SPEW(("jerryeds", "\n\nADDING PAGE : %d, UPDATE COUNT : %d - SIZE %d", page_number, entryCount, totalMaxSize)); Stuff::ChainIteratorOf iterator(&m_UpdateEntries); NetUpdateSortEntry *entry; while ((entry = iterator.ReadAndNext()) != NULL) { //SPEW(("jerryeds", "%s : %s : size %d", Update_Text_Table[entry->m_type], Text_Table[entry->m_rate], entry->m_size)); page->MakeDictionaryParagraph(entry->m_entity, entry->m_type, entry->m_rate); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetUpdateSorter::NetUpdateSorter(int debug_level, int connection_rate): Plug(DefaultData), m_halfhzList(NULL), m_oneHzList(NULL), m_twoHzList(NULL), m_threeHzList(NULL), m_fourHzList(NULL), m_sixHzList(NULL), m_eightHzList(NULL), m_nineHzList(NULL), m_twelveHzList(NULL), m_sixteenHzList(NULL) { m_bandwidth = connection_rate; m_debugLevel = debug_level; updateList[0] = &m_halfhzList; updateList[1] = &m_oneHzList; updateList[2] = &m_twoHzList; updateList[3] = &m_threeHzList; updateList[4] = &m_fourHzList; updateList[5] = &m_sixHzList; updateList[6] = &m_eightHzList; updateList[7] = &m_nineHzList; updateList[8] = &m_twelveHzList; updateList[9] = &m_sixteenHzList; // dictionary version 8bit // page number 8bit // full ping time stamp 64bit pageOverhead = 16+64; paragraphOverhead = 1; switch(debug_level) { case 1: pageOverhead += 8; break; case 2: pageOverhead += 16; paragraphOverhead += 8; break; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetUpdateSorter::~NetUpdateSorter() { updateList[0]->DeletePlugs(); updateList[1]->DeletePlugs(); updateList[2]->DeletePlugs(); updateList[3]->DeletePlugs(); updateList[4]->DeletePlugs(); updateList[5]->DeletePlugs(); updateList[6]->DeletePlugs(); updateList[7]->DeletePlugs(); updateList[8]->DeletePlugs(); updateList[9]->DeletePlugs(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void NetUpdateSorter::AddUpdateToList(Entity *entity, int type, UpdateRate rate) { UpdateEntry *update = &UpdateManager::UpdateEntries[type]; int size = (update->m_maxSize)(entity, m_debugLevel, m_bandwidth); NetUpdateSortEntry *entry = new NetUpdateSortEntry(entity, size, type, rate); Verify(rate.m_ActiveRate >= 0); Verify(rate.m_ActiveRate < 10); Verify(rate.m_InactiveRate >= 0); Verify(rate.m_InactiveRate < 10); Check_Object(updateList[rate.m_ActiveRate]); updateList[rate.m_ActiveRate]->Add(entry); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void NetUpdateSorter::MakeDictionaryPages(Dictionary *dictionary) { // sort by like packets first... // remember: anyway i cut it the cull bit will allways be sent // the cull bit costs only go down if I only use like // update rates ChainOf twos_pages(NULL); ChainOf threes_pages(NULL); ChainOf *sub_list[4]; int twos_count = 0; sub_list[0] = &m_sixteenHzList; sub_list[1] = &m_eightHzList; sub_list[2] = &m_fourHzList; sub_list[3] = &m_twoHzList; for (int i = 0; i < 4; ++i) { Stuff::ChainIteratorOf iterator(sub_list[i]); NetUpdateSortEntry *entry; while ((entry = iterator.GetCurrent()) != NULL) { ++twos_count; FindPageWithRoom(&twos_pages, entry); iterator.Remove(); } } sub_list[0] = &m_twelveHzList; sub_list[1] = &m_nineHzList; sub_list[2] = &m_sixHzList; sub_list[3] = &m_threeHzList; int threes_count = 0; for (i = 0; i < 4; ++i) { Stuff::ChainIteratorOf iterator(sub_list[i]); NetUpdateSortEntry *entry; while ((entry = iterator.GetCurrent()) != NULL) { ++threes_count; FindPageWithRoom(&threes_pages, entry); iterator.Remove(); } } sub_list[0] = &m_oneHzList; sub_list[1] = &m_halfhzList; int page_count = 0; if (twos_count) { for (i = 0; i < 2; ++i) { Stuff::ChainIteratorOf iterator(sub_list[i]); NetUpdateSortEntry *entry; while ((entry = iterator.GetCurrent()) != NULL) { ++twos_count; FindPageWithRoom(&twos_pages, entry); iterator.Remove(); } } Stuff::ChainIteratorOf iterator(&twos_pages); NetUpdatePageHolder *page; while ((page = iterator.ReadAndNext()) != NULL) { page->AddSelfToDictionary(dictionary, page_count); ++page_count; } } if (threes_count) { for (i = 0; i < 2; ++i) { Stuff::ChainIteratorOf iterator(sub_list[i]); NetUpdateSortEntry *entry; while ((entry = iterator.GetCurrent()) != NULL) { ++threes_count; FindPageWithRoom(&threes_pages, entry); iterator.Remove(); } } Stuff::ChainIteratorOf iterator(&threes_pages); NetUpdatePageHolder *page; while ((page = iterator.ReadAndNext()) != NULL) { page->AddSelfToDictionary(dictionary, page_count); ++page_count; } } #ifdef _ARMOR Verify(!updateList[0]->GetSize()); Verify(!updateList[1]->GetSize()); Verify(!updateList[2]->GetSize()); Verify(!updateList[3]->GetSize()); Verify(!updateList[4]->GetSize()); Verify(!updateList[5]->GetSize()); Verify(!updateList[6]->GetSize()); Verify(!updateList[7]->GetSize()); Verify(!updateList[8]->GetSize()); Verify(!updateList[9]->GetSize()); #endif twos_pages.DeletePlugs(); threes_pages.DeletePlugs(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void NetUpdateSorter::FindPageWithRoom(ChainOf *pages, NetUpdateSortEntry *entry) { Stuff::ChainIteratorOf iterator(pages); NetUpdatePageHolder *page; while ((page = iterator.ReadAndNext()) != NULL) { if (page->IsThereRoom(entry, paragraphOverhead)) { page->AddToList(entry, paragraphOverhead); return; } } NetUpdatePageHolder *new_page = new NetUpdatePageHolder(pageOverhead); pages->Add(new_page); new_page->AddToList(entry, paragraphOverhead); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~