Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
547 lines
13 KiB
C++
547 lines
13 KiB
C++
#pragma once
|
|
|
|
#include "node.h"
|
|
#include "chain.h"
|
|
#include "memblock.h"
|
|
#include "memstrm.h"
|
|
|
|
class Receiver__SharedData;
|
|
class Receiver__InheritanceSet;
|
|
struct Receiver__HandlerEntry;
|
|
class Receiver__MessageHandlerSet;
|
|
class Receiver__Message;
|
|
class Receiver__DynamicMessage;
|
|
class Derivation;
|
|
class Event;
|
|
class DynamicMemoryStream;
|
|
class MessageTap;
|
|
|
|
//##########################################################################
|
|
//########################## Receiver ################################
|
|
//##########################################################################
|
|
//
|
|
// It is suggested that calls to methods meant to be serviced by a receiver
|
|
// be built through inline functions in the derived class, rather than
|
|
// having to build the parameter block in the scope of the caller. Letting
|
|
// the inline code build the parameter block is much cleaner, and allows the
|
|
// message code numbers to be held inside the derived class, further
|
|
// protecting against calling methods for objects not in a proper derivation
|
|
// chain.
|
|
//
|
|
class Receiver:
|
|
public Node
|
|
{
|
|
//##########################################################################
|
|
// Shared Data Support
|
|
//
|
|
public:
|
|
typedef Receiver__SharedData SharedData;
|
|
SharedData*
|
|
GetSharedData() const;
|
|
|
|
static Derivation* GetClassDerivations();
|
|
Derivation*
|
|
GetDerivation() const;
|
|
|
|
static SharedData DefaultData;
|
|
|
|
Logical
|
|
IsDerivedFrom(Derivation& parent) const;
|
|
Logical
|
|
IsDerivedFrom(const char* parent) const;
|
|
|
|
protected:
|
|
const SharedData* sharedData;
|
|
|
|
//##########################################################################
|
|
// Construction and Destruction Support
|
|
//
|
|
protected:
|
|
Receiver(
|
|
ClassID class_ID,
|
|
SharedData &shared_data
|
|
):
|
|
Node(class_ID),
|
|
sharedData(&shared_data)
|
|
{}
|
|
|
|
Receiver(
|
|
PlugStream *stream,
|
|
SharedData &shared_data
|
|
):
|
|
Node(stream),
|
|
sharedData(&shared_data)
|
|
{}
|
|
|
|
//##########################################################################
|
|
// Messaging Support
|
|
//
|
|
public:
|
|
typedef Receiver__Message Message;
|
|
typedef Receiver__DynamicMessage DynamicMessage;
|
|
typedef Receiver__InheritanceSet InheritanceSet;
|
|
typedef Receiver__HandlerEntry HandlerEntry;
|
|
typedef Receiver__MessageHandlerSet MessageHandlerSet;
|
|
typedef void (Receiver::*Handler)(const Message*);
|
|
typedef Enumeration MessageID;
|
|
|
|
enum {
|
|
AnyMessageID=0,
|
|
WatcherChangedMessageID,
|
|
LoadResourceFinishedMessageID,
|
|
NextMessageID
|
|
};
|
|
|
|
static const Handler NullHandler;
|
|
|
|
void
|
|
Receive(Message *What);
|
|
|
|
virtual void
|
|
Dispatch(Message *What)
|
|
{Receive(What);}
|
|
|
|
void
|
|
DefaultMessageHandler(Message*);
|
|
|
|
typedef void (Receiver::*ScanCallback)(
|
|
Receiver::Message *message,
|
|
Receiver *receiver
|
|
);
|
|
|
|
MessageTap*
|
|
MakeMessageTap(
|
|
Derivation *derivation,
|
|
ScanCallback callback
|
|
);
|
|
MessageTap*
|
|
MakeMessageTap(
|
|
Derivation *derivation,
|
|
ScanCallback callback,
|
|
Receiver::MessageID matching_message,
|
|
Receiver *match_receiver
|
|
);
|
|
|
|
protected:
|
|
static const HandlerEntry MessageHandlerEntries[];
|
|
// swapping the commented line for the following one due to inconsitincies
|
|
// in the order of initialization for static member variables
|
|
//static MessageHandlerSet MessageHandlers;
|
|
static MessageHandlerSet& GetMessageHandlers();
|
|
|
|
//##########################################################################
|
|
// Event Support
|
|
//
|
|
public:
|
|
virtual void
|
|
Receive(Event *event);
|
|
|
|
void
|
|
FlushEvents(int max_priority=-1);
|
|
void
|
|
FlushMatchingEvents(
|
|
MessageID target_message,
|
|
int max_priority=-1
|
|
);
|
|
|
|
void
|
|
ProcessDeferredQueue();
|
|
|
|
//##########################################################################
|
|
// Test Support
|
|
//
|
|
public:
|
|
static Logical
|
|
TestClass();
|
|
Logical
|
|
TestInstance() const;
|
|
};
|
|
|
|
//##########################################################################
|
|
//###################### Receiver::Message ###########################
|
|
//##########################################################################
|
|
|
|
class Receiver__Message
|
|
{
|
|
public:
|
|
#if defined(USE_SIGNATURE)
|
|
friend int
|
|
Is_Signature_Bad(const volatile Receiver__Message *);
|
|
#endif
|
|
|
|
size_t
|
|
messageLength;
|
|
Receiver::MessageID
|
|
messageID;
|
|
|
|
enum {
|
|
ReliableBit,
|
|
NextBit
|
|
};
|
|
|
|
enum {
|
|
ReliableFlag = 1 << ReliableBit
|
|
};
|
|
|
|
LWord
|
|
messageFlags;
|
|
|
|
Receiver__Message(
|
|
Receiver::MessageID id,
|
|
size_t message_length
|
|
):
|
|
messageID(id),
|
|
messageLength(message_length),
|
|
messageFlags(ReliableFlag) // HACK
|
|
{}
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
};
|
|
|
|
//##########################################################################
|
|
//################### Receiver::DynamicMessage #######################
|
|
//##########################################################################
|
|
|
|
class Receiver__DynamicMessage:
|
|
public DynamicMemoryStream
|
|
{
|
|
public:
|
|
Receiver__DynamicMessage()
|
|
{}
|
|
Receiver__DynamicMessage(
|
|
void *stream_start,
|
|
size_t stream_size,
|
|
size_t initial_offset=0
|
|
):
|
|
DynamicMemoryStream(stream_start, stream_size, initial_offset)
|
|
{}
|
|
Receiver__DynamicMessage(
|
|
Receiver::MessageID message_ID,
|
|
size_t size = sizeof(Receiver::Message)
|
|
);
|
|
|
|
Receiver::Message*
|
|
GetMessagePointer()
|
|
{Check(this); return Cast_Object(Receiver::Message*, streamStart);}
|
|
|
|
protected:
|
|
MemoryStream&
|
|
WriteBytes(
|
|
const void *ptr,
|
|
size_t number_of_bytes
|
|
);
|
|
};
|
|
|
|
//##########################################################################
|
|
//#################### ReceiverDataMessageOf #########################
|
|
//##########################################################################
|
|
|
|
template <class T> class ReceiverDataMessageOf:
|
|
public Receiver::Message
|
|
{
|
|
public:
|
|
T
|
|
dataContents;
|
|
|
|
ReceiverDataMessageOf(
|
|
Receiver::MessageID id,
|
|
size_t message_length,
|
|
const T& data
|
|
):
|
|
Receiver::Message(id, message_length),
|
|
dataContents(data)
|
|
{}
|
|
};
|
|
|
|
//##########################################################################
|
|
//######################### MessageTap ###############################
|
|
//##########################################################################
|
|
|
|
class MessageTap:
|
|
public Plug
|
|
{
|
|
//##########################################################################
|
|
// MessageTap Functionality
|
|
//
|
|
public:
|
|
MessageTap(
|
|
Derivation *derivation,
|
|
Receiver *client,
|
|
Receiver::ScanCallback callback
|
|
);
|
|
MessageTap(
|
|
Derivation *derivation,
|
|
Receiver *client,
|
|
Receiver::ScanCallback callback,
|
|
Receiver::MessageID matching_message,
|
|
Receiver *match_receiver
|
|
);
|
|
|
|
private:
|
|
Receiver::ScanCallback scanCallback;
|
|
Receiver* clientReceiver;
|
|
Receiver* matchingReceiver;
|
|
Receiver::MessageID matchingMessageID;
|
|
|
|
public:
|
|
void
|
|
Scan(
|
|
Receiver *receiver,
|
|
Receiver::Message *message
|
|
);
|
|
|
|
//##########################################################################
|
|
// Memory Allocation
|
|
//
|
|
private:
|
|
static MemoryBlock* GetAllocatedMemory();
|
|
|
|
public:
|
|
void* operator new(size_t) { return GetAllocatedMemory()->New(); }
|
|
void operator delete(void *where) { GetAllocatedMemory()->Delete(where); }
|
|
|
|
//##########################################################################
|
|
// Test support
|
|
//
|
|
public:
|
|
Logical
|
|
TestInstance() const;
|
|
static Logical
|
|
TestClass();
|
|
};
|
|
|
|
//##########################################################################
|
|
//################## Receiver::InheritanceSet ########################
|
|
//##########################################################################
|
|
//
|
|
// NOTE: An InheritanceSet generated for a class should only be inherited by
|
|
// other classes derived from that base class. If this is not done,
|
|
// SEVERE run-time weirdness will happen
|
|
//
|
|
class Receiver__InheritanceSet SIGNATURED
|
|
{
|
|
public:
|
|
Logical
|
|
TestInstance() const;
|
|
Enumeration
|
|
GetEntryCount()
|
|
{Check(this); return entryCount;}
|
|
|
|
protected:
|
|
Enumeration
|
|
entryCount;
|
|
|
|
Receiver__InheritanceSet()
|
|
{}
|
|
~Receiver__InheritanceSet()
|
|
{}
|
|
};
|
|
|
|
//##########################################################################
|
|
//################### Receiver::HandlerEntry #########################
|
|
//##########################################################################
|
|
|
|
struct Receiver__HandlerEntry
|
|
{
|
|
Enumeration
|
|
entryID;
|
|
const char*
|
|
entryName;
|
|
Receiver::Handler
|
|
entryHandler;
|
|
};
|
|
|
|
#define MESSAGE_ENTRY(class,message)\
|
|
{\
|
|
class::message##MessageID,\
|
|
#message,\
|
|
(Receiver::Handler)&class::message##MessageHandler\
|
|
}
|
|
|
|
//##########################################################################
|
|
//################# Receiver::MessageHandlerSet ######################
|
|
//##########################################################################
|
|
|
|
class Receiver__MessageHandlerSet:
|
|
public Receiver__InheritanceSet
|
|
{
|
|
//##########################################################################
|
|
// Constructors and Destructors
|
|
//
|
|
public:
|
|
Receiver__MessageHandlerSet(Receiver::MessageID count, const Receiver::HandlerEntry handler_table[], const Receiver::MessageHandlerSet &inheritance) { Build(count, handler_table, &inheritance); }
|
|
Receiver__MessageHandlerSet(Receiver::MessageID count, const Receiver::HandlerEntry handler_table[]) { Build(count, handler_table, NULL); }
|
|
Receiver__MessageHandlerSet(const Receiver::MessageHandlerSet& source) { Build(0, NULL, &source); }
|
|
Receiver__MessageHandlerSet()
|
|
{
|
|
messageHandlers = NULL;
|
|
entryCount = 0;
|
|
}
|
|
~Receiver__MessageHandlerSet();
|
|
|
|
protected:
|
|
void
|
|
Build(
|
|
Receiver::MessageID count,
|
|
const Receiver::HandlerEntry handler_table[],
|
|
const Receiver::MessageHandlerSet *inheritance
|
|
);
|
|
|
|
//##########################################################################
|
|
// HandlerSet Functionality
|
|
//
|
|
public:
|
|
static const Receiver::MessageHandlerSet
|
|
NullSet;
|
|
|
|
Receiver::Handler Find(Receiver::MessageID message) const
|
|
{
|
|
Check(this);
|
|
Verify(message > 0);
|
|
return (message<=entryCount) ? messageHandlers[message-1].entryHandler : Receiver::NullHandler;
|
|
}
|
|
|
|
const Receiver::HandlerEntry*
|
|
Find(const char* name) const;
|
|
|
|
const char *
|
|
GetName(Receiver::MessageID message) const
|
|
{
|
|
Check(this);
|
|
return (message<=entryCount)
|
|
? messageHandlers[message-1].entryName
|
|
: NULL;
|
|
}
|
|
|
|
protected:
|
|
Receiver::HandlerEntry* messageHandlers;
|
|
|
|
//##########################################################################
|
|
// Test Support
|
|
//
|
|
public:
|
|
static Logical
|
|
TestClass();
|
|
};
|
|
|
|
//##########################################################################
|
|
//########################## Derivation ##############################
|
|
//##########################################################################
|
|
|
|
class Derivation:
|
|
public Node
|
|
{
|
|
friend class Receiver;
|
|
|
|
//##########################################################################
|
|
// Construction and Destruction
|
|
//
|
|
public:
|
|
Derivation(char *who);
|
|
Derivation(Derivation *parent,char *who);
|
|
|
|
char *className;
|
|
|
|
//##########################################################################
|
|
// Messagetap support
|
|
//
|
|
private:
|
|
Derivation(Derivation& copy);
|
|
ChainOf<MessageTap*>
|
|
activeTaps;
|
|
|
|
public:
|
|
void
|
|
AppendMessageTap(MessageTap* tap);
|
|
Logical
|
|
IsDescendedFrom(Derivation& parent);
|
|
Logical
|
|
IsDescendedFrom(const char* parent);
|
|
|
|
//##########################################################################
|
|
// Inheritance Registration Support
|
|
//
|
|
private:
|
|
ChainOf<Derivation*>
|
|
classDerivations;
|
|
|
|
void
|
|
AppendDerivation(Derivation* child)
|
|
{Check(this); classDerivations.Add(child);}
|
|
|
|
//##########################################################################
|
|
// Test Support
|
|
//
|
|
public:
|
|
static Logical
|
|
TestClass();
|
|
};
|
|
|
|
//##########################################################################
|
|
//################### Receiver::SharedData ##########################
|
|
//##########################################################################
|
|
|
|
class Receiver__SharedData SIGNATURED
|
|
{
|
|
public:
|
|
Receiver__SharedData(
|
|
Derivation* derivation,
|
|
Receiver::MessageHandlerSet &handler
|
|
):
|
|
derivedClasses(derivation),
|
|
activeMessageHandlers(&handler)
|
|
{
|
|
//activeMessageHandlers = &activeMessageHandlersInstance;
|
|
}
|
|
|
|
Derivation *derivedClasses;
|
|
Receiver::MessageHandlerSet *activeMessageHandlers;
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
//private:
|
|
// Receiver::MessageHandlerSet activeMessageHandlersInstance;
|
|
};
|
|
|
|
inline Receiver::SharedData*
|
|
Receiver::GetSharedData() const
|
|
{Check(this); return Cast_Object(SharedData*,sharedData);}
|
|
|
|
inline Derivation*
|
|
Receiver::GetDerivation() const
|
|
{Check(this); return GetSharedData()->derivedClasses;}
|
|
|
|
inline Logical
|
|
Receiver::IsDerivedFrom(Derivation& parent) const
|
|
{return sharedData->derivedClasses->IsDescendedFrom(parent);}
|
|
|
|
inline Logical
|
|
Receiver::IsDerivedFrom(const char* parent) const
|
|
{Check(this); return GetDerivation()->IsDescendedFrom(parent);}
|
|
|
|
inline MessageTap*
|
|
Receiver::MakeMessageTap(
|
|
Derivation *derivation,
|
|
ScanCallback callback
|
|
)
|
|
{Check(this); return new MessageTap(derivation, this, callback);}
|
|
|
|
inline MessageTap*
|
|
Receiver::MakeMessageTap(
|
|
Derivation *derivation,
|
|
ScanCallback callback,
|
|
Receiver::MessageID matching_message,
|
|
Receiver *match_receiver
|
|
)
|
|
{
|
|
Check(this);
|
|
return new MessageTap(
|
|
derivation,
|
|
this,
|
|
callback,
|
|
matching_message,
|
|
match_receiver
|
|
);
|
|
}
|