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.
447 lines
12 KiB
C++
447 lines
12 KiB
C++
//===========================================================================//
|
|
// File: receiver.cc //
|
|
// Project: MUNGA Brick: Dynamic Dispatch //
|
|
// Contents: Implementation Details of Dynamic Dispatch Processing //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 10/19/94 JMA Initial coding. //
|
|
// 10/28/94 JMA Made compatible with SGI CC //
|
|
// 11/03/94 ECH Made compatible with BC4.0 //
|
|
// 11/05/94 JMA Made compatible with GNU C++ //
|
|
// 11/30/94 JMA Adapted to new style conventions //
|
|
// 12/01/94 JMA Made compatible with SGI CC //
|
|
// 12/04/94 JMA Moved Message under Receiver, merged with message.hh //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// PROPRIETARY AND CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "AdeptHeaders.hpp"
|
|
|
|
//#############################################################################
|
|
//############################# Receiver ################################
|
|
//#############################################################################
|
|
|
|
const Receiver::MessageHandler
|
|
Receiver::NullMessageHandler=NULL;
|
|
|
|
const Receiver::MessageEntry
|
|
Receiver::MessageEntries[]=
|
|
{
|
|
MESSAGE_ENTRY(Receiver, Default)
|
|
};
|
|
|
|
Receiver::ClassData*
|
|
Receiver::DefaultData = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Receiver::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
ReceiverClassID,
|
|
"Adept::Receiver",
|
|
Plug::DefaultData,
|
|
ELEMENTS(MessageEntries), MessageEntries
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Receiver::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Receiver::Receiver(ClassData *class_data):
|
|
Plug(class_data)
|
|
{
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Receiver::DefaultMessageHandler(const Message* message)
|
|
{
|
|
SPEW((0, "Default Handler activated on message ID %d", message->messageID));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Receiver::Receive(const Message *what)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(what);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Now, see if the receiver can handle this type of message, and if so, send
|
|
// the message to the returned method handler
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
ClassData *class_data = GetClassData();
|
|
Check_Object(class_data);
|
|
MessageHandler handler = class_data->GetMessageHandler(what->messageID);
|
|
Verify(handler != Receiver::NullMessageHandler);
|
|
#if defined(_DEBUG) && 0 // jcem - for MR test
|
|
{
|
|
char Buffer[128];
|
|
sprintf(Buffer, "Receiver:: %s\n", class_data->messageHandlers[what->messageID-1].messageName);
|
|
OutputDebugString(Buffer);
|
|
}
|
|
#endif // _DEBUG && ...
|
|
(this->*handler)(what);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Receiver::Receive(Event *event)
|
|
{
|
|
Receive(event->messageToSend);
|
|
Unregister_Object(event);
|
|
delete event;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Receiver::FlushEvents(int) // max_priority doesn't work yet!!!!
|
|
{
|
|
Check_Object(this);
|
|
STOP(("Not implemented"));
|
|
#if 0
|
|
PlugIteratorOf<Event*> i(this);
|
|
Event *event;
|
|
while ((event = i.ReadAndNext()) != NULL)
|
|
{
|
|
if (event->GetClassID() == EventClassID)
|
|
{
|
|
Unregister_Object(event);
|
|
delete event;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Receiver::FlushMatchingEvents(
|
|
Receiver::MessageID target_message,
|
|
int // max_priority doesn't work yet!!!!
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
STOP(("Not implemented"));
|
|
#if 0
|
|
PlugIteratorOf<Event*>
|
|
i(this);
|
|
Event* event;
|
|
while ((event = i.ReadAndNext()) != NULL)
|
|
{
|
|
if (
|
|
event->GetClassID() == EventClassID && (
|
|
target_message == Receiver::AnyMessageID
|
|
|| event->messageToSend->messageID == target_message
|
|
)
|
|
)
|
|
{
|
|
Unregister_Object(event);
|
|
delete event;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Receiver::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//#############################################################################
|
|
//############################# ClassData ##############################
|
|
//#############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Receiver__ClassData::Receiver__ClassData(
|
|
RegisteredClass::ClassID class_id,
|
|
const char *class_name,
|
|
Plug::ClassData *parent,
|
|
Receiver::MessageID count,
|
|
const Receiver::MessageEntry *handler_table
|
|
):
|
|
Plug__ClassData(class_id, class_name, parent)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
//
|
|
//----------------------------
|
|
// Look for our parent's table
|
|
//----------------------------
|
|
//
|
|
Receiver__ClassData *inheritance;
|
|
if (class_id != ReceiverClassID)
|
|
{
|
|
inheritance = Cast_Pointer(Receiver__ClassData*, parent);
|
|
Check_Object(inheritance);
|
|
}
|
|
else
|
|
{
|
|
Verify(parent->GetClassID() == PlugClassID);
|
|
inheritance = NULL;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// If we have not supplied a message table, use our parents table
|
|
//---------------------------------------------------------------
|
|
//
|
|
if (count == 0 && inheritance != NULL)
|
|
{
|
|
Check_Object(inheritance);
|
|
deleteMessages = false;
|
|
messageHandlers = inheritance->messageHandlers;
|
|
messageCount = inheritance->messageCount;
|
|
return;
|
|
}
|
|
|
|
//
|
|
//---------------------------------
|
|
// We will have to make a new table
|
|
//---------------------------------
|
|
//
|
|
deleteMessages = true;
|
|
Check_Pointer(handler_table);
|
|
Verify(count > 0);
|
|
|
|
//
|
|
//-------------------------------------------------------
|
|
// Find out the highest message type we have to deal with
|
|
//-------------------------------------------------------
|
|
//
|
|
messageCount = 0;
|
|
Receiver::MessageID i;
|
|
for (i=0; i<count; ++i)
|
|
{
|
|
if (handler_table[i].messageID > messageCount)
|
|
{
|
|
messageCount = handler_table[i].messageID;
|
|
}
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------
|
|
// Adjust the table size to include our parent stuff
|
|
//--------------------------------------------------
|
|
//
|
|
if (inheritance)
|
|
{
|
|
Verify(messageCount <= inheritance->messageCount + count);
|
|
if (messageCount < inheritance->messageCount)
|
|
{
|
|
messageCount = inheritance->messageCount;
|
|
}
|
|
#if defined(_ARMOR)
|
|
else if (messageCount > inheritance->messageCount)
|
|
{
|
|
i = inheritance->messageCount+1;
|
|
goto Check_Table;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------
|
|
// Make sure that there are no holes in the table
|
|
//-----------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
Verify(messageCount == count);
|
|
#if defined(_ARMOR)
|
|
i = 1;
|
|
Check_Table:
|
|
while (i <= messageCount)
|
|
{
|
|
int j;
|
|
for (j=0; j<count; ++j)
|
|
{
|
|
if (handler_table[j].messageID == i)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (j == count)
|
|
{
|
|
break;
|
|
}
|
|
++i;
|
|
}
|
|
Verify(i > count);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Allocate the memory for the new handler set, and copy the inherited
|
|
// handlers to the new table. We are guaranteed to have enough space for
|
|
// the inherited table
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
messageHandlers = new Receiver::MessageEntry[messageCount];
|
|
Register_Pointer(messageHandlers);
|
|
i = 0;
|
|
if (inheritance)
|
|
{
|
|
for (; i<inheritance->messageCount; ++i)
|
|
{
|
|
messageHandlers[i] = inheritance->messageHandlers[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Step through the new table supplied, placing each handler in the slot
|
|
// determined by the message type
|
|
//----------------------------------------------------------------------
|
|
//
|
|
for (i=0; i<count; ++i)
|
|
{
|
|
Receiver::MessageID index = handler_table[i].messageID - 1;
|
|
Verify(index >= 0 && index < messageCount);
|
|
messageHandlers[index] = handler_table[i];
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Receiver__ClassData::~Receiver__ClassData()
|
|
{
|
|
if (deleteMessages)
|
|
{
|
|
Unregister_Pointer(messageHandlers);
|
|
delete[] messageHandlers;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
size_t
|
|
Receiver__ClassData::WriteClassBlock(
|
|
MemoryStream* stream,
|
|
bool write_it
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
int size = 0;
|
|
|
|
//
|
|
//----------------------------------------------------------------
|
|
// If we are just finding out the size of the class, figure it out
|
|
//----------------------------------------------------------------
|
|
//
|
|
if (!write_it)
|
|
{
|
|
size += 2*sizeof(int);
|
|
size += strlen(GetClassName())+1;
|
|
int messages = GetMessageCount();
|
|
for (int i=1; i<=messages; ++i)
|
|
{
|
|
const Receiver::MessageEntry *entry = GetMessageEntry(i);
|
|
Check_Pointer(entry);
|
|
const char* name = entry->messageName;
|
|
Check_Pointer(name);
|
|
size += strlen(name) + 1;
|
|
}
|
|
size = (size+3)&~3;
|
|
}
|
|
|
|
//
|
|
//------------------------
|
|
// Otherwise, write it out
|
|
//------------------------
|
|
//
|
|
else
|
|
{
|
|
int messages = GetMessageCount();
|
|
*stream << GetClassID() << messages;
|
|
size_t str_len = strlen(GetClassName()) + 1;
|
|
stream->WriteBytes(className, str_len);
|
|
size = str_len;
|
|
for (int i=1; i<=messages; ++i)
|
|
{
|
|
const Receiver::MessageEntry *entry = GetMessageEntry(i);
|
|
Check_Pointer(entry);
|
|
const char* name = entry->messageName;
|
|
Check_Pointer(name);
|
|
str_len = strlen(name) + 1;
|
|
stream->WriteBytes(name, str_len);
|
|
size += str_len;
|
|
}
|
|
while (size&3)
|
|
{
|
|
*stream << '\0';
|
|
++size;
|
|
}
|
|
size = 0;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Now call all of our derived classes and add their sizes to the total
|
|
//---------------------------------------------------------------------
|
|
//
|
|
RegisteredClass__ClassData *class_data = firstChildClass;
|
|
while (class_data)
|
|
{
|
|
Receiver__ClassData *receiver_class =
|
|
Cast_Pointer(Receiver__ClassData*, class_data);
|
|
Check_Object(receiver_class);
|
|
size += receiver_class->WriteClassBlock(stream, write_it);
|
|
class_data = receiver_class->nextSiblingClass;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
const Receiver::MessageEntry*
|
|
Receiver__ClassData::FindMessageEntry(const char* name)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(name);
|
|
|
|
for (int i=0; i<messageCount; ++i)
|
|
{
|
|
if (!_stricmp(name, messageHandlers[i].messageName))
|
|
{
|
|
return &messageHandlers[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Receiver__ClassData::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(Receiver::DefaultData));
|
|
}
|