Files
firestorm/Gameleap/code/mw4/Libraries/Adept/Connection.cpp
T
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

608 lines
15 KiB
C++

//===========================================================================//
// File: Connection.cpp
// Project: MUNGA Brick: Replicator
// Contents:
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/24/97 JMA Infrastructure changes.
// 08/25/97 ECH Infrastructure changes. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1997, Virtual World Entertainment, Inc. //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#include "AdeptHeaders.hpp"
#include "Connection.hpp"
#include "Replicator.hpp"
//#define HUNT_BUG "your_loginname_here"
//#############################################################################
//######################### Connection ###########################
//#############################################################################
Connection*
Connection::Local = NULL;
Connection*
Connection::Server = NULL;
Connection*
Connection::Hermit = NULL;
const Receiver::MessageEntry
Connection::MessageEntries[]=
{
MESSAGE_ENTRY(Connection, Replicate),
MESSAGE_ENTRY(Connection, Replicator)
};
Connection::ClassData*
Connection::DefaultData = NULL;
Stuff::SafeChainOf<Replicator*>* g_pTempReplicators = NULL; // jcem
#ifdef _DEBUG
int g_nMechLabs = 0;
#endif // _DEBUG
//
//#############################################################################
//#############################################################################
//
void
Connection::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
ConnectionClassID,
"Adept::Connection",
InBox::DefaultData,
ELEMENTS(MessageEntries), MessageEntries
);
Register_Object(DefaultData);
}
//
//#############################################################################
//#############################################################################
//
void
Connection::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//
//#############################################################################
//#############################################################################
//
Connection::Connection(
BYTE id,
DWORD network_address,
const char *name
):
InBox(DefaultData, Network::ConnectionBoxID),
allReplicators(NULL),
nextReplicatorID(id)
{
Check_Pointer(this);
connectionID = id;
networkAddress = network_address;
connectionName = name;
bytesToTransfer = 0;
dataBuffer = NULL;
// we dont add here due to the fact we don't really know
// if this is the local connection or hermit connection at this point...
for (int i = 0; i < 8192; ++i)
{
usedConnections[i] = 0x0;
}
replicatorCount = 0;
}
//
//#############################################################################
//#############################################################################
//
Connection::~Connection()
{
if (Network::GetInstance() != NULL)
{
Network::GetInstance()->RemoveConnectionToStats(connectionID);
}
SafeChainIteratorOf<Replicator*> replicators(&allReplicators);
Replicator *replicator;
while ((replicator = replicators.GetCurrent()) != NULL)
{
Check_Object(replicator);
Unregister_Object(replicator);
delete replicator;
replicators.First();
}
}
//
//#############################################################################
//#############################################################################
//
void
Connection::DeleteChildren(void)
{
SafeChainIteratorOf<Replicator*> replicators(&allReplicators);
Replicator *replicator;
while ((replicator = replicators.GetCurrent()) != NULL)
{
Check_Object(replicator);
Unregister_Object(replicator);
delete replicator;
replicators.First();
}
nextReplicatorID = ReplicatorID(connectionID);
for (int i = 0; i < 8192; ++i)
{
usedConnections[i] = 0x0;
}
replicatorCount = 0;
}
//
//#############################################################################
//#############################################################################
//
void
Connection::ReplicateMessageHandler(
const Replicator::CreateMessage *message
)
{
Check_Object(this);
Check_Object(message);
Verify(message->messageID == ReplicateMessageID);
//
//-----------------------------------------------------------
// Get the class data for the object to be replicated and the
// make method
//-----------------------------------------------------------
//
RegisteredClass::ClassData *class_data =
RegisteredClass::FindClassData(message->classID);
Check_Object(class_data);
Verify(class_data->IsDerivedFrom(Replicator::DefaultData));
Replicator::Factory make_method =
Cast_Pointer(Replicator::ClassData*, class_data)->replicatorFactory;
Check_Pointer(make_method);
//
//--------------------
// Execute make method
//--------------------
//
ReplicatorID base_id = message->replicatorID;
(*make_method)(message, &base_id);
}
//
//#############################################################################
//#############################################################################
//
void
Connection::ReplicatorMessageHandler(
const Message *manager_message
)
{
Check_Object(this);
Check_Object(manager_message);
Verify(manager_message->messageID == ReplicatorMessageID);
//
//---------------------------
// Get message for replicator
//---------------------------
//
const Replicator::Message *replicator_message =
reinterpret_cast<const Replicator::Message*>(
reinterpret_cast<const char*>(manager_message)
+ sizeof(*manager_message)
);
Check_Object(replicator_message);
Verify(replicator_message->replicatorID != ReplicatorID::Null);
#if defined(HUNT_BUG)
SPEW((
HUNT_BUG,
"Received message for %d:%d",
replicator_message->replicatorID.connectionID,
replicator_message->replicatorID.localID
));
#endif
//
//--------------------
// Find the replicator
//--------------------
//
Replicator *replicator = FindReplicator(replicator_message->replicatorID);
//
//----------------------------------------------
// If the replicator exists, send it the message
//----------------------------------------------
//
if (replicator)
{
Check_Object(replicator);
replicator->Receive(replicator_message);
}
}
//
//#############################################################################
//#############################################################################
//
const ReplicatorID&
Connection::GetNextReplicatorID()
{
if (!this) {
Check_Object(Connection::Hermit);
return Connection::Hermit->GetNextReplicatorID();
}
Check_Object(this);
++nextReplicatorID.localID;
int loop_killer = 0;
while (ISConnectionUsed(nextReplicatorID.localID))
{
++nextReplicatorID.localID;
if (loop_killer > 65537)
STOP(("No connections Left"));
loop_killer++;
}
return nextReplicatorID;
}
//
//#############################################################################
//#############################################################################
//
void
Connection::AddReplicator(Replicator *replicator)
{
Check_Object(this);
Check_Object(replicator);
//
//---------------------------------------------
// Make sure that the replicator is safe to use
//---------------------------------------------
//
Verify(!FindReplicator(replicator->GetReplicatorID()));
allReplicators.Add(replicator);
Verify(replicator->GetReplicatorID().connectionID == connectionID);
if (replicator->GetReplicatorID().localID > nextReplicatorID.localID)
{
nextReplicatorID.localID = replicator->GetReplicatorID().localID;
}
ReplicatorCreated(replicator);
if (g_pTempReplicators) { // jcem
g_pTempReplicators->Add(replicator);
#ifdef _DEBUG
gosASSERT(g_nMechLabs == 1);
#endif // _DEBUG
} else {
#ifdef _DEBUG
gosASSERT(g_nMechLabs <= 1);
#endif // _DEBUG
}
}
//
//#############################################################################
//#############################################################################
//
void
Connection::RemoveReplicator(Replicator *replicator)
{
Check_Object(this);
Check_Object(replicator);
//
//---------------------------------------------
// Make sure that the replicator is safe to use
//---------------------------------------------
//
ReplicatorDestroyed(replicator);
Check_Object(FindReplicator(replicator->GetReplicatorID()));
allReplicators.RemovePlug(replicator);
replicator->owningConnection = NULL;
}
//
//#############################################################################
//#############################################################################
//
void
Connection::ReplicatorCreated(
Replicator *replicator
)
{
Check_Object(this);
Check_Object(replicator);
SetConnectionUsed(replicator->GetReplicatorID().localID);
++replicatorCount;
#ifdef _ARMOR
if (Stuff::ArmorLevel > 2)
{
Verify(allReplicators.GetSize() == replicatorCount);
}
#endif
}
//
//#############################################################################
//#############################################################################
//
void
Connection::ReplicatorDestroyed(Replicator *replicator)
{
Check_Object(this);
ClearConnectionUsed(replicator->GetReplicatorID().localID);
--replicatorCount;
#ifdef _ARMOR
if (Stuff::ArmorLevel > 2)
{
Verify(allReplicators.GetSize()-1 == replicatorCount);
}
#endif
}
//
//#############################################################################
//#############################################################################
//
void
Connection::SetConnectionUsed(int connection)
{
Verify(!ISConnectionUsed(connection));
Check_Object(this);
Verify(connection < 65536);
int byte = connection>>3;
int bit = connection&0x7;
Verify(byte < 8192);
usedConnections[byte] |= 0x1<<bit;
}
//
//#############################################################################
//#############################################################################
//
void
Connection::ClearConnectionUsed(int connection)
{
Check_Object(this);
Verify(connection < 65536);
Verify(ISConnectionUsed(connection));
int byte = connection>>3;
int bit = connection&0x7;
Verify(byte < 8192);
usedConnections[byte] &= ~(0x1<<bit);
Verify(!ISConnectionUsed(connection));
}
//
//#############################################################################
//#############################################################################
//
bool
Connection::ISConnectionUsed(int connection)
{
Check_Object(this);
Verify(connection < 65536);
int byte = connection>>3;
int bit = connection&0x7;
Verify(byte < 8192);
Check_Object(this);
return (usedConnections[byte]&(0x1<<bit))?true:false;
}
//
//#############################################################################
//#############################################################################
//
void
Connection::SendToMaster(
Replicator *replicator,
const Replicator::Message *replicator_message
)
{
Check_Object(this);
Check_Object(replicator);
Check_Object(replicator_message);
Verify(replicator->GetReplicatorMode() == Replicator::ReplicantMode);
Verify(replicator_message->replicatorID != ReplicatorID::Null);
//
//------------------------------------------------
// Build a network message in dynamic build buffer
//------------------------------------------------
//
#if defined(HUNT_BUG)
SPEW((
HUNT_BUG,
"Sending message to master %d:%d",
replicator_message->replicatorID.connectionID,
replicator_message->replicatorID.localID
));
#endif
size_t total_size =
sizeof(Message) + replicator_message->messageLength;
DynamicMemoryStream build_buffer(total_size);
Message *manager_message =
new (build_buffer.GetPointer()) Message(
ReplicatorMessageID,
total_size,
0,
replicator_message->messageFlags
);
Check_Object(manager_message);
build_buffer.AdvancePointer(sizeof(*manager_message));
Mem_Copy(
build_buffer.GetPointer(),
replicator_message,
replicator_message->messageLength,
build_buffer.GetBytesRemaining()
);
//
//-------------
// Send message
//-------------
//
Send(manager_message, replicator->owningConnection);
}
//
//#############################################################################
//#############################################################################
//
void
Connection::BroadcastToReplicants(
Replicator *replicator,
const Replicator::Message *replicator_message
)
{
Check_Object(this);
Check_Object(replicator);
Check_Object(replicator_message);
Verify(replicator->GetReplicatorMode() == Replicator::MasterMode);
Verify(replicator_message->replicatorID != ReplicatorID::Null);
#if defined(HUNT_BUG)
SPEW((
HUNT_BUG,
"Sending message to replicants of %d:%d",
replicator_message->replicatorID.connectionID,
replicator_message->replicatorID.localID
));
#endif
//
//------------------------------------------------
// Build a network message in dynamic build buffer
//------------------------------------------------
//
size_t total_size =
sizeof(Message) + replicator_message->messageLength;
DynamicMemoryStream build_buffer(total_size);
Message *manager_message =
new (build_buffer.GetPointer()) Message(
ReplicatorMessageID,
total_size,
0,
replicator_message->messageFlags
);
Check_Object(manager_message);
build_buffer.AdvancePointer(sizeof(*manager_message));
Mem_Copy(
build_buffer.GetPointer(),
replicator_message,
replicator_message->messageLength,
build_buffer.GetBytesRemaining()
);
//
//-------------
// Send message
//-------------
//
ExclusiveBroadcast(manager_message);
}
//
//#############################################################################
//#############################################################################
//
Replicator*
Connection::FindReplicator(const ReplicatorID &id)
{
Check_Object(this);
Check_Object(&id);
Connection *connection;
connection = this;
if(id.connectionID != connectionID)
{
Check_Object(Network::GetInstance());
connection = Network::GetInstance()->GetConnection(id.connectionID);
}
//
//--------------------------------------------------------------------
// For now, we will spin through the loop. This will not be good soon
//--------------------------------------------------------------------
//
SafeChainIteratorOf<Replicator*> replicators(&connection->allReplicators);
Replicator *replicator;
while ((replicator = replicators.ReadAndNext()) != NULL)
{
Check_Object(replicator);
if (replicator->GetReplicatorID() == id)
return replicator;
}
return NULL;
}
void Connection::DeleteReplicator(Replicator* p)
{
delete p;
}