Here is a basic overview of the system.
#pragma once
#ifndef IR_MESSAGE_DISPATCHER_H
#define IR_MESSAGE_DISPATCHER_H
#include <set>
#include "Object.h"
#include "../script/angel/scripthandle.h"
#undef DispatchMessage
namespace Irre {
struct Telegram
{
Telegram( double delay,
asIScriptObject* sender,
asIScriptObject* receiver,
int message,
CScriptHandle& data )
: Sender( sender ),
Receiver( receiver ),
Message( message ),
DispatchTime( delay ),
Data( data )
{
Sender->AddRef();
Receiver->AddRef();
}
~Telegram()
{
Sender->Release();
Receiver->Release();
}
asIScriptObject* Sender;
asIScriptObject* Receiver;
int Message;
double DispatchTime;
CScriptHandle Data;
bool operator<=( const Telegram& other ) { return DispatchTime <= other.DispatchTime; }
bool operator==( const Telegram& other ) { return DispatchTime == other.DispatchTime; }
};
class MessageDispatcher
{
public:
void TransmitMessage( double delay,
Object* sender,
Object* receiver,
int msg,
CScriptHandle& data );
void DispatchDelayedMessages();
private:
void Discharge(Object* receiver,const Telegram& message);
std::set<Telegram> m_DelayedTelegrams;
};
}
#endif
#include "MessageDispatcher.h"
#include "../shared/Global.h"
#include "../script/angel/ScriptFunctions.h"
#include "Stage.h"
#include "ObjectManager.h"
#include "Engine.h"
namespace Irre {
void MessageDispatcher::TransmitMessage( double delay,
Object* sender,
Object* receiver,
int msg,
CScriptHandle& data)
{
float current_time = IR_GetTick();
Telegram message(0,sender->m_Core,receiver->m_Core,msg,data );
if( delay == 0 ) Discharge( receiver, message );
}
void MessageDispatcher::Discharge( Object* receiver,const Telegram& message )
{
receiver->ReceiveMessage( message );
}
void MessageDispatcher::DispatchDelayedMessages()
{
// Not implemented yet.
}
}
void RegisterDispatchMessage( asIScripeEngine* e )
{
// Registering the global function.
r=e->RegisterGlobalFunction("void IR_DispatchMessage(double,int,int,int,ref&in)", asFUNCTION(IR_DispatchMessage), asCALL_CDECL); AS_CHECK(r);
}
/* Dummy */
void TelegramDummy( Telegram* self ) { }
void TelegramDestructor( Telegram* self )
{
((Telegram*)self)->~Telegram();
}
void RegisterTelegram( asIScriptEngine* e )
{
r=e->RegisterObjectType("Telegram",sizeof(Telegram),asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CD );AS_CHECK(r);
r=e->RegisterObjectBehaviour("Telegram",asBEHAVE_CONSTRUCT,"void f()",asFUNCTION(TelegramDummy),asCALL_CDECL_OBJLAST);AS_CHECK(r);
r=e->RegisterObjectBehaviour("Telegram",asBEHAVE_DESTRUCT,"void f()",asFUNCTION(TelegramDestructor),asCALL_CDECL_OBJLAST);AS_CHECK(r);
r=e->RegisterObjectProperty("Telegram","IObject@ Sender",offsetof(Telegram,Sender));
r=e->RegisterObjectProperty("Telegram","IObject@ Receiver",offsetof(Telegram,Receiver));
r=e->RegisterObjectProperty("Telegram","int Message",offsetof(Telegram,Message));
r=e->RegisterObjectProperty("Telegram","double DispatchTime",offsetof(Telegram,DispatchTime));
r=e->RegisterObjectProperty("Telegram","ref@ Data",offsetof(Telegram,Data));
}
void OnMessageReceived( const Telegram&in message )
{
switch( message.Message )
{
case TA_Messages::BODY_WITHIN_RADAR_RANGE:
{
TA_Body@ sensed_body = cast<TA_Body@>(message.Data); // The data is null when it gets passed to IsFriendly.
if( sensed_body is null ) Println("The sensed body was null for whatever reason.");
if( !IsFriendly(sensed_body) && !IsDead )
{
m_SensoryMemory.SaveMemoryEntry( TA_MemoryRecord(sensed_body.TA_Mind,sensed_body.Position) );
}
} break;
case TA_Messages::AGENT_ORDER_DROP_EVERYTHING:
case TA_Messages::AGENT_ORDER_PATROL:
case TA_Messages::AGENT_ORDER_WEAPONS_FREE:
case TA_Messages::AGENT_ORDER_DEFEND:
case TA_Messages::AGENT_ORDER_SEEK_AND_DESTROY:
{
DispatchMessage( 0,m_ThinkGoal,message.Message,message.Data );
} break;
}
By the way, I know for a fact that the data that gets passed to the telegram in the first place is guaranteed to not be null. And yes, I am well aware of interfaces and such, but I find messaging to be much more convenient than using interfaces for everything. I have also tried using a pointer to the CScriptHandle, but that eventually leads to either a segfault or an assertion.