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.
608 lines
15 KiB
C++
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;
|
|
}
|