Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

947 lines
24 KiB
C++

//===========================================================================//
// File: Dictionary.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 "Dictionary.hpp"
#include "MWEntityManager.hpp"
#include "NetUpdateManager.hpp"
#include "MWApplication.hpp"
#include "Adept\NetStatCollector.hpp"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar OneCycle = 2.0f;
Scalar HerzPreSec[DictionaryPage::UpdateCycleCount] =
{
0.5f, //double of the hrz since we are in a 2 second cycle..
1.0f,
2.0f,
3.0f,
4.0f,
6.0f,
8.0f,
9.0f,
12.0f,
16.0f
};
int Translation_Table[DictionaryPage::UpdateCycleCount] =
{
DictionaryPage::HalfhzType,
DictionaryPage::OneHzType,
DictionaryPage::TwoHzType,
DictionaryPage::ThreeHzType,
DictionaryPage::FourHzType,
DictionaryPage::SixHzType,
DictionaryPage::EightHzType,
DictionaryPage::NineHzType,
DictionaryPage::TwelveHzType,
DictionaryPage::SixteenHzType
};
//##########################################################################
//########################### DictionaryParagraph
//##########################################################################
DictionaryParagraph::DictionaryParagraph():
Plug(DefaultData),
entitySlot(NULL)
{
activeUpdateCycle = 0x0;
inactiveUpdateCycle = 0x0;
active = true;
activeCycle = -1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DictionaryParagraph::DictionaryParagraph(Entity *entity, int message_type, int active_update_cycle, int inactive_update_cycle):
Plug(DefaultData),
entitySlot(NULL)
{
Check_Object(entity);
entitySlot.Add(entity);
NetVerify(message_type > UpdateManager::BaseUpdateID);
NetVerify(message_type < UpdateManager::UpdateCount);
messageType = message_type;
activeUpdateCycle = active_update_cycle;
inactiveUpdateCycle = inactive_update_cycle;
active = true;
activeCycle = 0;
entityVariableMessageSize = -1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DictionaryParagraph::~DictionaryParagraph()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DictionaryParagraph::Encode(Stuff::DynamicMemoryStream* memory_stream, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
Entity *entity = entitySlot.GetCurrent();
Check_Object(entity);
ReplicatorID rep_id = entity->GetReplicatorID();
UpdateEntry *update = &UpdateManager::UpdateEntries[messageType];
(update->m_encode)(entity, memory_stream, connection, debug_level, bandwidth);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DictionaryParagraph::Decode(Stuff::MemoryStream* memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
Entity *entity = entitySlot.GetCurrent();
if (entity != NULL)
{
Check_Object(entity);
ReplicatorID rep_id = entity->GetReplicatorID();
UpdateEntry *update = &UpdateManager::UpdateEntries[messageType];
int rate_type = BitDepthManager::GetUpdateRate(update->m_updateID, bandwidth).m_ActiveRate;
Scalar rate = DictionaryPage::CalculateSeconds(rate_type);
(*update->m_decode)(entity, memory_stream, till, packet_latency, connection, debug_level, bandwidth, rate);
}
else
{
UpdateEntry *update = &UpdateManager::UpdateEntries[messageType];
(*update->m_skip)(memory_stream, entityVariableMessageSize, till, connection, debug_level, bandwidth);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool DictionaryParagraph::ReadyToUpdate(int cycles_to_update)
{
if (active)
{
if (activeUpdateCycle & cycles_to_update)
return true;
}
else
{
if (inactiveUpdateCycle & cycles_to_update)
return true;
}
return false;
}
//##########################################################################
//########################### DictionaryPage
//##########################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DictionaryPage::DictionaryPage(int page_number):
Plug(DefaultData),
dictionaryParagraphs(NULL)
{
pageNumber = page_number;
paragraphCount = 0;
usedUpdateCycle = 0x0;
lastExecuted = -2.0f;
timeFromLastSlowestUpdate = 0.0f;
lastPacketNumber = 0;
for (int i = 0; i < UpdateCycleCount; ++i)
{
currentCycleCount[i] = 0;
}
if (pageNumber >= MaximumPages)
STOP(("DictionaryPage::DictionaryPage:TOO MANY PAGES"));
NetVerify(pageNumber > -1);
NetVerify(pageNumber < MaximumPages);
Time current_time = gos_GetElapsedTime();
for (i = 0; i < 8; ++i)
{
activeCycles[i] = current_time;
current_time += 0.25;
}
currentActiveCycle = 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DictionaryPage::~DictionaryPage()
{
Stuff::ChainIteratorOf<DictionaryParagraph*> iterator(&dictionaryParagraphs);
Stuff::Plug *plug;
while ((plug = iterator.GetCurrent()) != NULL)
{
iterator.Remove();
Check_Object(plug);
delete plug;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DictionaryPage::Encode(Stuff::DynamicMemoryStream* memory_stream, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
Stuff::ChainIteratorOf<DictionaryParagraph*> iterator(&dictionaryParagraphs);
int paragraph_count = 0;
++lastPacketNumber;
if (lastPacketNumber == 255)
lastPacketNumber = 0;
MWEntityManager *manager = Cast_Object(MWEntityManager*, EntityManager::GetInstance());
NetVerify(manager->serverController != NULL);
Scalar current_time = (float)(gos_GetElapsedTime(1) * 1000.0);
memory_stream->WriteBits(&lastPacketNumber, 8);
memory_stream->WriteBits(&manager->serverController->lastPingDelta[connection], 32);
memory_stream->WriteBits(&current_time, 32);
//SPEWALWAYS(("jerryeds", "S-SEND - %d : t2-t1 : %f, t3 : %f", lastPacketNumber, manager->serverController->lastPingDelta[connection], current_time));
//SPEW(("jerryeds", "ENCODE: packet %d", lastPacketNumber));
//SPEW(("jerryeds", "ENCODE: t1 %d", manager->serverController->lastPingDelta[connection]));
//SPEW(("jerryeds", "ENCODE: t2 %d", current_time));
if (debug_level > 1)
{
BYTE magic_number = 0xAA;
memory_stream->WriteBits(&magic_number, 8);
//SPEW(("jerryeds", "ENCODE: MAGIC"));
Network::GetInstance()->netStatCollector[Network::OutgoingHeaderBitSizeStat].AddToStatistic(connection,8);
}
DictionaryParagraph *paragraph;
while ((paragraph = iterator.ReadAndNext()) != NULL)
{
if (paragraph->ReadyToUpdate(cyclesToUpdate))
{
memory_stream->WriteBit(true);
paragraph->Encode(memory_stream, connection, debug_level, bandwidth);
}
else
{
memory_stream->WriteBit(false);
}
if (debug_level > 1)
{
memory_stream->WriteBits(&paragraph_count, 8);
Network::GetInstance()->netStatCollector[Network::OutgoingHeaderBitSizeStat].AddToStatistic(connection,8);
}
++paragraph_count;
}
if (debug_level > 0)
{
BYTE magic_number = 0xAA;
memory_stream->WriteBits(&magic_number, 8);
Network::GetInstance()->netStatCollector[Network::OutgoingHeaderBitSizeStat].AddToStatistic(connection,8);
}
Network::GetInstance()->netStatCollector[Network::OutgoingHeaderBitSizeStat].AddToStatistic(connection,paragraph_count + 8);
Network::GetInstance()->netStatCollector[Network::OutgoingHeaderBitSizeStat].AddToStatistic(connection,64);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DictionaryPage::Decode(Stuff::MemoryStream* memory_stream, Time till, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
// throw out old ones
BYTE packet_number;
Scalar t2_minus_t1;
Scalar t3;
memory_stream->ReadBits(&packet_number, 8);
memory_stream->ReadBits(&t2_minus_t1, 32);
memory_stream->ReadBits(&t3, 32);
//SPEW(("jerryeds", "DECODE: packet %d", packet_number));
//SPEW(("jerryeds", "DECODE: t1 %d", t2_minus_t1));
//SPEW(("jerryeds", "DECODE: t2 %d", t3));
if (debug_level > 1)
{
BYTE magic_number = 0;
memory_stream->ReadBits(&magic_number, 8);
Network::GetInstance()->netStatCollector[Network::IncomingHeaderBitSizeStat].AddToStatistic(connection,8);
//SPEW(("jerryeds", "DECODE: MAGIC"));
if(magic_number != 0xAA)
{
STOP(("UPDATE HEADER PAGE READ ERROR: %d",pageNumber));
}
}
//SPEWALWAYS(("jerryeds", "DICTIONARY LATENCY : %f", packet_latency));
if (MWEntityManager::IsNumberBehind(packet_number, lastPacketNumber, 40, 255))
{
#if defined(LAB_ONLY)
SPEWALWAYS(("jerryeds", "LATE DICTIONARY PACKET THROWN OUT"));
#endif
return;
}
MWEntityManager *manager = Cast_Object(MWEntityManager*, EntityManager::GetInstance());
Scalar t4 = (float)(gos_GetElapsedTime(1) * 1000.0);
manager->clientController->lastPingDelta = t4 - t3;
MWApplication::GetInstance()->servedConnectionData[connection].effectivePing = t2_minus_t1 + (t4 - t3);
//SPEWALWAYS(("jerryeds", "C-REC - %d : t2-t1 : %f, t4-t3 %f : t3 : %f t4 : %f", packet_number, t2_minus_t1, t4 - t3, t3, t4));
Scalar packet_latency = MWApplication::GetInstance()->servedConnectionData[connection].effectivePing * 0.5f;
Min_Clamp(packet_latency, 1.0f);
packet_latency *= 0.001f;
//SPEWALWAYS(("jerryeds", "latency : %f\n", packet_latency));
lastPacketNumber = packet_number;
lastExecuted = till;
Stuff::ChainIteratorOf<DictionaryParagraph*> iterator(&dictionaryParagraphs);
int paragraph_count = 0;
DictionaryParagraph *paragraph;
while ((paragraph = iterator.ReadAndNext()) != NULL)
{
bool noskip_bit;
memory_stream->ReadBit(noskip_bit);
if (noskip_bit)
paragraph->Decode(memory_stream, till, packet_latency, connection, debug_level, bandwidth);
if (debug_level > 1)
{
int debug_paragraph_count = 0;
memory_stream->ReadBits(&debug_paragraph_count, 8);
Network::GetInstance()->netStatCollector[Network::IncomingHeaderBitSizeStat].AddToStatistic(connection,8);
if (debug_paragraph_count != paragraph_count)
{
Entity *entity = paragraph->entitySlot.GetCurrent();
if (entity != NULL && entity->instanceName)
{
STOP(("UPDATE PARAGRAPH READ ERROR: %s : Page %d, Paragraph %d, Type %d", (char*)entity->instanceName, pageNumber, paragraph_count, paragraph->messageType));
}
else
{
STOP(("UPDATE PARAGRAPH READ ERROR: NO ENTITY : Page %d, Paragraph %d, Type %d", pageNumber, paragraph_count, paragraph->messageType));
}
}
}
++paragraph_count;
}
if (debug_level > 0)
{
BYTE magic_number;
memory_stream->ReadBits(&magic_number, 8);
Network::GetInstance()->netStatCollector[Network::IncomingHeaderBitSizeStat].AddToStatistic(connection,8);
if(magic_number != 0xAA)
{
STOP(("UPDATE PAGE READ ERROR: %d",pageNumber));
}
}
Network::GetInstance()->netStatCollector[Network::IncomingHeaderBitSizeStat].AddToStatistic(connection,paragraph_count+8);
Network::GetInstance()->netStatCollector[Network::IncomingHeaderBitSizeStat].AddToStatistic(connection,64);
}
Scalar DictionaryPage::CalculateSeconds(int type)
{
Verify(type >= 0);
Verify(type <= UpdateCycleCount);
return 1.0f / HerzPreSec[type];
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int DictionaryPage::CalculateCycles(Time till)
{
Scalar time_slice = static_cast<Stuff::Scalar>(till - lastExecuted);
lastExecuted = till;
//increment the time from the last full cycle.
//The full cycle is OneCycle, which is also the
//slowest cycle.
timeFromLastSlowestUpdate += time_slice;
// calculate the carryover if there is any.
Scalar carryover = 0;
int carryover_count = 0;
if (timeFromLastSlowestUpdate > OneCycle)
{
// how many cycles it carried over
carryover_count = (int)(timeFromLastSlowestUpdate / OneCycle);
// how far past the last cycle it carried over
carryover = timeFromLastSlowestUpdate - (carryover_count * OneCycle);
}
// calculate the cycle counts
int cycle_triggers = 0x0;
for (int i = 0; i < UpdateCycleCount; ++i)
{
// this is how many times this cycle should have triggered
int cycles_triggered = (int)(timeFromLastSlowestUpdate*HerzPreSec[i]);
// if we haven't triggered that many times than trigger one
if (cycles_triggered > currentCycleCount[i])
{
// add the cycle to the bit mask
cycle_triggers |= (0x1<<i);
// we only want to update once so
// rather than increment we just go ahead
// and equal up to how many we should have
// updated.
currentCycleCount[i] = cycles_triggered;
}
// subtract the carryover if there is any
// if not the carryover_count will be zero and
// nothing will happen.
currentCycleCount[i] -= (int)(carryover_count * HerzPreSec[i] * OneCycle);
}
if (carryover_count)
{
timeFromLastSlowestUpdate = carryover;
}
return cycle_triggers;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool DictionaryPage::MaintainCycles(Time till, int connection_id)
{
Time largest_time = activeCycles[0];
bool flip[8];
bool req_update = false;
Point3D cull_location;
cull_location = MWApplication::GetInstance()->servedConnectionData[connection_id].vehiclePosition;
// reset the counters
for (int i = 0; i < 8; ++i)
{
flip[i] = false;
if (till - activeCycles[i] > 2.0)
{
flip[i] = true;
activeCycles[i] += 2.0;
// deactivate any cylces that are on this cycle..
// if this is the largest time to flip this frame
// than this is the currentactivecycle.
if (largest_time < activeCycles[i])
{
largest_time = activeCycles[i];
currentActiveCycle = i;
}
}
}
// maintain the paragraphs active states
DictionaryParagraph *paragraph;
Stuff::ChainIteratorOf<DictionaryParagraph*> iterator(&dictionaryParagraphs);
while ((paragraph = iterator.ReadAndNext()) != NULL)
{
if (paragraph->active && flip[paragraph->activeCycle])
{
paragraph->active = false;
paragraph->activeCycle = -1;
}
UpdateEntry *update = &UpdateManager::UpdateEntries[paragraph->messageType];
if ((update->m_maintainActiveFlag)(paragraph->entitySlot.GetCurrent(), cull_location))
{
paragraph->active = true;
paragraph->activeCycle = currentActiveCycle;
}
if (paragraph->ReadyToUpdate(cyclesToUpdate))
{
req_update = true;
}
}
return req_update;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
DictionaryPage::RequireUpdate(Time new_time, int connection_id)
{
cyclesToUpdate = CalculateCycles(new_time);
bool require_update = MaintainCycles(new_time, connection_id);
return require_update;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DictionaryParagraph *
DictionaryPage::MakeDictionaryParagraph(Entity *entity, int message_type, UpdateRate update_cycle)
{
usedUpdateCycle |= Translation_Table[update_cycle.m_ActiveRate];
usedUpdateCycle |= Translation_Table[update_cycle.m_InactiveRate];
DictionaryParagraph *paragraph = new DictionaryParagraph(entity, message_type, Translation_Table[update_cycle.m_ActiveRate], Translation_Table[update_cycle.m_InactiveRate]);
Check_Object(paragraph);
dictionaryParagraphs.Add(paragraph);
++paragraphCount;
//NetVerify(paragraphCount < 64);
return paragraph;
}
//##########################################################################
//########################### Dictionary
//##########################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Dictionary::Dictionary(int version_number, int connection, int debug_level, int bandwidth):
Plug(DefaultData),
dictionaryPages(NULL, true)
{
versionNumber = version_number;
connectionID = connection;
debugDictionaryLevel = debug_level;
dictionaryBandwidth = bandwidth;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Dictionary::Dictionary(int version_number, int connection):
Plug(DefaultData),
dictionaryPages(NULL, true)
{
versionNumber = version_number;
connectionID = connection;
debugDictionaryLevel = -1;
dictionaryBandwidth = -1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Dictionary::~Dictionary()
{
Stuff::SortedChainIteratorOf<DictionaryPage*, int> iterator(&dictionaryPages);
Stuff::Plug *plug;
while ((plug = iterator.GetCurrent()) != NULL)
{
iterator.Remove();
Check_Object(plug);
delete plug;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Dictionary::Encode(Time till)
{
Stuff::SortedChainIteratorOf<DictionaryPage*, int> iterator(&dictionaryPages);
DictionaryPage *page;
while ((page = iterator.ReadAndNext()) != NULL)
{
if (page->RequireUpdate(till, connectionID))
{
DynamicMemoryStream memory_stream(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize);
// make stream
// write dictionary format
memory_stream.WriteBits(&versionNumber, 8);
//SPEW(("jerryeds", "ENCODE: version %d", versionNumber));
// write page data
page->Encode(&memory_stream, connectionID, debugDictionaryLevel, dictionaryBandwidth);
memory_stream.WriteByteAlign();
memory_stream.Rewind();
NetVerify(memory_stream.GetBufferBytesUsed() > 0);
// send page
Network::GetInstance()->SendNetMessage(
connectionID, MWEntityManager::DictionaryPage0MessageID + page->pageNumber, &memory_stream, false);
Network::GetInstance()->netStatCollector[Network::OutgoingHeaderBitSizeStat].AddToStatistic(connectionID,4);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Dictionary::Decode(int message_type, Stuff::MemoryStream* memory_stream, Time till)
{
Check_Object(memory_stream);
int version = 0;
memory_stream->ReadBits(&version, 8);
//SPEW(("jerryeds", "DECODE: version %d", version));
Network::GetInstance()->netStatCollector[Network::IncomingHeaderBitSizeStat].AddToStatistic(connectionID,4);
if (version != versionNumber)
return;
Stuff::SortedChainIteratorOf<DictionaryPage*, int> iterator(&dictionaryPages);
int page_index = message_type - MWEntityManager::DictionaryPage0MessageID;
DictionaryPage *page = iterator.Find(page_index);
if (page == NULL)
STOP(("Dictionary::Decode : Page in dictionary not found"));
Check_Object(page);
page->Decode(memory_stream, till, Connection::Local->GetID(), debugDictionaryLevel, dictionaryBandwidth);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DictionaryPage *
Dictionary::MakeDictionaryPage(int page_number)
{
NetVerify(page_number > -1);
NetVerify(page_number < MaximumPages);
DictionaryPage *page = new DictionaryPage(page_number);
Check_Object(page);
dictionaryPages.AddValue(page, page_number);
return page;
}
//##########################################################################
//########################### DictionaryManager
//##########################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DictionaryManager::DictionaryManager(int connection):
Plug(DefaultData),
dictionaryIndex(NULL, true)
{
activeDictionaryIndex = -1;
activeDictionary = NULL;
connectionID = connection;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DictionaryManager::~DictionaryManager()
{
Stuff::SortedChainIteratorOf<Dictionary*, int> iterator(&dictionaryIndex);
Stuff::Plug *plug;
while ((plug = iterator.GetCurrent()) != NULL)
{
iterator.Remove();
Check_Object(plug);
delete plug;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Dictionary *
DictionaryManager::MakeNewDictionary(int version_number, int debug_level, int bandwidth)
{
// server keeps old copies but the client remove them
SortedChainIteratorOf<Dictionary*, int> iterator(&dictionaryIndex);
if (!Application::GetInstance()->serverFlag)
{
// clients remove all old dictionaries
Stuff::SortedChainIteratorOf<Dictionary*, int> iterator(&dictionaryIndex);
Stuff::Plug *plug;
while ((plug = iterator.GetCurrent()) != NULL)
{
iterator.Remove();
Check_Object(plug);
delete plug;
}
}
else
{
// we are the server, we only care about the last one and the new one...
// remove everything but the old one and the new one...
Stuff::SortedChainIteratorOf<Dictionary*, int> iterator(&dictionaryIndex);
Stuff::Plug *plug;
while ((plug = iterator.GetCurrent()) != NULL)
{
if (iterator.GetValue() != activeDictionaryIndex)
{
iterator.Remove();
Check_Object(plug);
delete plug;
}
else
{
iterator.Next();
}
}
}
activeDictionaryIndex = version_number;
activeDictionary = new Dictionary(activeDictionaryIndex, connectionID, debug_level, bandwidth);
Check_Object(activeDictionary);
Dictionary* test = dictionaryIndex.Find(activeDictionaryIndex);
if (test != NULL)
{
Unregister_Object(test);
delete (test);
}
dictionaryIndex.AddValue(activeDictionary, activeDictionaryIndex);
return activeDictionary;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
DictionaryManager::GetNextDictionaryID()
{
int next_dictionary = activeDictionaryIndex;
if (next_dictionary == 254)
{
next_dictionary = 0;
}
else
{
++next_dictionary;
}
return next_dictionary;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Dictionary *
DictionaryManager::GetCurrentDictionary()
{
NetVerify(activeDictionaryIndex >= 0);
Check_Object(activeDictionary);
return activeDictionary;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Dictionary *
DictionaryManager::GetDictionary(int version)
{
// if it is already here we need to remove it...
SortedChainIteratorOf<Dictionary*, int> iterator(&dictionaryIndex);
Dictionary *dictionary = iterator.Find(version);
return dictionary;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DictionaryManager::Encode(Time till)
{
activeDictionary->Encode(till);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DictionaryManager::Decode(int message_type, Stuff::MemoryStream* memory_stream)
{
NetVerify(message_type >= MWEntityManager::DictionaryPage0MessageID && message_type <= MWEntityManager::DictionaryPageMaxMessageID);
if (activeDictionary == NULL)
return;
// change till to the packet latency...
activeDictionary->Decode(message_type, memory_stream, 0.0f);
}