Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
394 lines
9.9 KiB
C++
394 lines
9.9 KiB
C++
//===========================================================================//
|
|
// 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<NetUpdateSortEntry*> 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<NetUpdatePageHolder*> twos_pages(NULL);
|
|
ChainOf<NetUpdatePageHolder*> threes_pages(NULL);
|
|
|
|
ChainOf<NetUpdateSortEntry*> *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<NetUpdateSortEntry*> 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<NetUpdateSortEntry*> 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<NetUpdateSortEntry*> iterator(sub_list[i]);
|
|
NetUpdateSortEntry *entry;
|
|
while ((entry = iterator.GetCurrent()) != NULL)
|
|
{
|
|
++twos_count;
|
|
FindPageWithRoom(&twos_pages, entry);
|
|
iterator.Remove();
|
|
}
|
|
}
|
|
|
|
Stuff::ChainIteratorOf<NetUpdatePageHolder*> 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<NetUpdateSortEntry*> iterator(sub_list[i]);
|
|
NetUpdateSortEntry *entry;
|
|
while ((entry = iterator.GetCurrent()) != NULL)
|
|
{
|
|
++threes_count;
|
|
FindPageWithRoom(&threes_pages, entry);
|
|
iterator.Remove();
|
|
}
|
|
}
|
|
|
|
Stuff::ChainIteratorOf<NetUpdatePageHolder*> 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<NetUpdatePageHolder*> *pages, NetUpdateSortEntry *entry)
|
|
{
|
|
|
|
Stuff::ChainIteratorOf<NetUpdatePageHolder*> 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);
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|