2004-07-04 17:41:17 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
2006-06-02 04:10:27 +02:00
|
|
|
#include "lib/lib.h"
|
2003-11-25 03:11:50 +01:00
|
|
|
#include <stdio.h>
|
2004-08-16 17:19:17 +02:00
|
|
|
#include <map>
|
2003-11-25 03:11:50 +01:00
|
|
|
|
2006-06-02 04:10:27 +02:00
|
|
|
#include "simulation/Entity.h"
|
2006-06-02 05:56:24 +02:00
|
|
|
#include "ps/Vector2D.h"
|
2003-11-25 03:11:50 +01:00
|
|
|
#define ALLNETMSGS_IMPLEMENT
|
|
|
|
|
|
|
|
#include "NetMessage.h"
|
2004-08-16 17:19:17 +02:00
|
|
|
|
2006-06-02 04:10:27 +02:00
|
|
|
#include "ps/CLogger.h"
|
2004-08-16 17:19:17 +02:00
|
|
|
|
|
|
|
#define LOG_CAT_NET "net"
|
2003-11-25 03:11:50 +01:00
|
|
|
|
2006-11-12 05:02:36 +01:00
|
|
|
// Please don't modify the deserializer map outside the ONCE-block in DeserializeMessage
|
2004-03-08 03:04:34 +01:00
|
|
|
typedef std::map <ENetMessageType, NetMessageDeserializer> MessageDeserializerMap;
|
2003-11-25 03:11:50 +01:00
|
|
|
MessageDeserializerMap g_DeserializerMap;
|
|
|
|
|
2004-09-21 16:40:43 +02:00
|
|
|
CNetMessage::~CNetMessage()
|
|
|
|
{
|
|
|
|
m_Type=NMT_NONE;
|
|
|
|
}
|
|
|
|
|
2004-03-08 03:04:34 +01:00
|
|
|
u8 *CNetMessage::Serialize(u8 *pos) const
|
|
|
|
{ return pos; }
|
2003-11-25 03:11:50 +01:00
|
|
|
|
|
|
|
uint CNetMessage::GetSerializedLength() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-03-08 03:04:34 +01:00
|
|
|
CStr CNetMessage::GetString() const
|
2004-09-21 16:40:43 +02:00
|
|
|
{
|
|
|
|
if (m_Type==NMT_NONE)
|
|
|
|
return "NMT_NONE { Invalid Message }";
|
|
|
|
else
|
|
|
|
return CStr("Unknown Message ")+CStr(m_Type);
|
|
|
|
}
|
2004-03-08 03:04:34 +01:00
|
|
|
|
2005-08-09 17:55:44 +02:00
|
|
|
const u8 *CNetMessage::Deserialize(const u8* pos, const u8* UNUSED(end))
|
|
|
|
{
|
|
|
|
return pos;
|
|
|
|
}
|
2004-03-08 03:04:34 +01:00
|
|
|
|
2004-08-16 17:19:17 +02:00
|
|
|
CNetMessage *CNetMessage::Copy() const
|
|
|
|
{
|
2004-09-21 16:40:43 +02:00
|
|
|
LOG(ERROR, LOG_CAT_NET, "CNetMessage::Copy(): Attempting to copy non-copyable message!");
|
|
|
|
return new CNetMessage(NMT_NONE);
|
2004-08-16 17:19:17 +02:00
|
|
|
}
|
|
|
|
|
2004-03-08 03:04:34 +01:00
|
|
|
CNetMessage *CNetMessage::DeserializeMessage(ENetMessageType type, u8 *buffer, uint length)
|
2003-11-25 03:11:50 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
ONCE(
|
|
|
|
SNetMessageDeserializerRegistration *pReg=&g_DeserializerRegistrations[0];
|
|
|
|
for (;pReg->m_pDeserializer;pReg++)
|
|
|
|
{
|
|
|
|
g_DeserializerMap.insert(std::make_pair(pReg->m_Type, pReg->m_pDeserializer));
|
|
|
|
}
|
2004-05-06 19:14:30 +02:00
|
|
|
);
|
2003-11-25 03:11:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
MessageDeserializerMap::const_iterator dEntry=g_DeserializerMap.find(type);
|
|
|
|
if (dEntry == g_DeserializerMap.end())
|
2004-08-16 17:19:17 +02:00
|
|
|
{
|
|
|
|
LOG(WARNING, LOG_CAT_NET, "Unknown message received on socket: type 0x%04x, length %u", type, length);
|
2003-11-25 03:11:50 +01:00
|
|
|
return NULL;
|
2004-08-16 17:19:17 +02:00
|
|
|
}
|
2003-11-25 03:11:50 +01:00
|
|
|
NetMessageDeserializer pDes=dEntry->second;
|
|
|
|
return (pDes)(buffer, length);
|
|
|
|
}
|
2004-03-08 03:04:34 +01:00
|
|
|
|
2005-05-18 07:32:09 +02:00
|
|
|
void CNetMessage::ScriptingInit()
|
|
|
|
{
|
|
|
|
#define def(_msg) g_ScriptingHost.DefineConstant(#_msg, _msg)
|
|
|
|
|
|
|
|
def(NMT_Goto);
|
2006-01-16 11:56:12 +01:00
|
|
|
def(NMT_Run);
|
2005-05-18 07:32:09 +02:00
|
|
|
def(NMT_Patrol);
|
|
|
|
def(NMT_AddWaypoint);
|
2005-12-29 09:42:44 +01:00
|
|
|
def(NMT_Generic);
|
2006-02-22 23:45:16 +01:00
|
|
|
def(NMT_Produce);
|
2006-05-04 09:40:31 +02:00
|
|
|
def(NMT_PlaceObject);
|
2006-02-13 04:31:26 +01:00
|
|
|
def(NMT_NotifyRequest);
|
2006-03-31 05:30:34 +02:00
|
|
|
def(NMT_FormationGoto);
|
|
|
|
def(NMT_FormationGeneric);
|
2006-08-28 05:07:48 +02:00
|
|
|
|
|
|
|
#undef def
|
2005-05-18 07:32:09 +02:00
|
|
|
}
|
|
|
|
|
2006-08-25 06:24:06 +02:00
|
|
|
CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSContext *cx, uintN argc, jsval *argv, bool isQueued)
|
2005-05-18 07:32:09 +02:00
|
|
|
{
|
2005-06-28 06:06:25 +02:00
|
|
|
debug_assert(argc >= 1);
|
2005-05-18 07:32:09 +02:00
|
|
|
|
|
|
|
int msgType;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2005-08-09 17:55:44 +02:00
|
|
|
msgType = ToPrimitive<int>( argv[0] );
|
2005-05-18 07:32:09 +02:00
|
|
|
}
|
|
|
|
catch(PSERROR_Scripting_ConversionFailed)
|
|
|
|
{
|
|
|
|
JS_ReportError(cx, "Invalid order type");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ArgumentCountError() STMT(\
|
|
|
|
JS_ReportError(cx, "Too few parameters!"); \
|
|
|
|
return NULL; )
|
|
|
|
#define ArgumentTypeError() STMT(\
|
|
|
|
JS_ReportError(cx, "Parameter type error!"); \
|
|
|
|
return NULL; )
|
|
|
|
#define ReadPosition(_msg, _field) \
|
|
|
|
try { \
|
|
|
|
if (argIndex+2 > argc) \
|
|
|
|
ArgumentCountError();\
|
|
|
|
if (!JSVAL_IS_INT(argv[argIndex]) || !JSVAL_IS_INT(argv[argIndex+1])) \
|
|
|
|
ArgumentTypeError(); \
|
2005-08-09 17:55:44 +02:00
|
|
|
_msg->_field ## X = ToPrimitive<int>(argv[argIndex++]); \
|
|
|
|
_msg->_field ## Y = ToPrimitive<int>(argv[argIndex++]); \
|
2005-05-18 07:32:09 +02:00
|
|
|
} catch (PSERROR_Scripting_ConversionFailed) { \
|
|
|
|
JS_ReportError(cx, "Invalid location"); \
|
|
|
|
return NULL; \
|
|
|
|
}
|
|
|
|
#define ReadEntity(_msg, _field) \
|
|
|
|
STMT(\
|
|
|
|
if (argIndex+1 > argc) \
|
|
|
|
ArgumentCountError(); \
|
|
|
|
if (!JSVAL_IS_OBJECT(argv[argIndex])) \
|
|
|
|
ArgumentTypeError(); \
|
|
|
|
CEntity *ent=ToNative<CEntity>(argv[argIndex++]); \
|
|
|
|
if (!ent) \
|
|
|
|
{ \
|
|
|
|
JS_ReportError(cx, "Invalid entity parameter"); \
|
|
|
|
return NULL; \
|
|
|
|
} \
|
|
|
|
_msg->_field=ent->me; \
|
|
|
|
)
|
2005-12-29 09:42:44 +01:00
|
|
|
#define ReadInt(_msg, _field) \
|
|
|
|
STMT(\
|
|
|
|
if (argIndex+1 > argc) \
|
|
|
|
ArgumentCountError(); \
|
|
|
|
if (!JSVAL_IS_INT(argv[argIndex])) \
|
|
|
|
ArgumentTypeError(); \
|
|
|
|
int val=ToPrimitive<int>(argv[argIndex++]); \
|
|
|
|
_msg->_field=val; \
|
|
|
|
)
|
2006-02-22 23:45:16 +01:00
|
|
|
#define ReadString(_msg, _field) \
|
|
|
|
STMT(\
|
|
|
|
if (argIndex+1 > argc) \
|
|
|
|
ArgumentCountError(); \
|
|
|
|
if (!JSVAL_IS_STRING(argv[argIndex])) \
|
|
|
|
ArgumentTypeError(); \
|
|
|
|
CStrW val=ToPrimitive<CStrW>(argv[argIndex++]); \
|
|
|
|
_msg->_field=val; \
|
|
|
|
)
|
2005-05-18 07:32:09 +02:00
|
|
|
|
|
|
|
#define PositionMessage(_msg) \
|
|
|
|
case NMT_ ## _msg: \
|
|
|
|
{ \
|
|
|
|
C##_msg *msg = new C##_msg(); \
|
2006-08-25 06:24:06 +02:00
|
|
|
msg->m_IsQueued = isQueued; \
|
2005-05-18 07:32:09 +02:00
|
|
|
msg->m_Entities = entities; \
|
|
|
|
ReadPosition(msg, m_Target); \
|
|
|
|
return msg; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define EntityMessage(_msg) \
|
|
|
|
case NMT_ ## _msg: \
|
|
|
|
{ \
|
|
|
|
C##_msg *msg = new C##_msg(); \
|
2006-08-25 06:24:06 +02:00
|
|
|
msg->m_IsQueued = isQueued; \
|
2005-05-18 07:32:09 +02:00
|
|
|
msg->m_Entities = entities; \
|
|
|
|
ReadEntity(msg, m_Target); \
|
|
|
|
return msg; \
|
|
|
|
}
|
2005-12-29 09:42:44 +01:00
|
|
|
|
|
|
|
#define EntityIntMessage(_msg) \
|
|
|
|
case NMT_ ## _msg: \
|
|
|
|
{ \
|
|
|
|
C##_msg *msg = new C##_msg(); \
|
2006-08-25 06:24:06 +02:00
|
|
|
msg->m_IsQueued = isQueued; \
|
2005-12-29 09:42:44 +01:00
|
|
|
msg->m_Entities = entities; \
|
|
|
|
ReadEntity(msg, m_Target); \
|
|
|
|
ReadInt(msg, m_Action); \
|
|
|
|
return msg; \
|
|
|
|
}
|
2005-05-18 07:32:09 +02:00
|
|
|
|
2006-02-22 23:45:16 +01:00
|
|
|
#define ProduceMessage(_msg) \
|
|
|
|
case NMT_ ## _msg: \
|
|
|
|
{ \
|
|
|
|
C##_msg *msg = new C##_msg(); \
|
2006-08-25 06:24:06 +02:00
|
|
|
msg->m_IsQueued = isQueued; \
|
2006-02-23 02:26:02 +01:00
|
|
|
msg->m_Entities = entities; \
|
2006-02-22 23:45:16 +01:00
|
|
|
ReadInt(msg, m_Type); \
|
|
|
|
ReadString(msg, m_Name); \
|
|
|
|
return msg; \
|
|
|
|
}
|
|
|
|
|
2006-05-04 09:40:31 +02:00
|
|
|
#define PlaceObjectMessage(_msg) \
|
|
|
|
case NMT_ ## _msg: \
|
|
|
|
{ \
|
|
|
|
C##_msg *msg = new C##_msg(); \
|
2006-08-25 06:24:06 +02:00
|
|
|
msg->m_IsQueued = isQueued; \
|
2006-05-04 09:40:31 +02:00
|
|
|
msg->m_Entities = entities; \
|
|
|
|
ReadString(msg, m_Template); \
|
|
|
|
ReadInt(msg, m_X); \
|
|
|
|
ReadInt(msg, m_Y); \
|
|
|
|
ReadInt(msg, m_Z); \
|
|
|
|
ReadInt(msg, m_Angle); \
|
|
|
|
return msg; \
|
|
|
|
}
|
|
|
|
|
2005-05-18 07:32:09 +02:00
|
|
|
// argIndex, incremented by reading macros. We have already "eaten" the
|
|
|
|
// first argument (message type)
|
|
|
|
uint argIndex = 1;
|
|
|
|
switch (msgType)
|
|
|
|
{
|
|
|
|
// NMT_Goto, targetX, targetY
|
|
|
|
PositionMessage(Goto)
|
2006-01-16 11:56:12 +01:00
|
|
|
PositionMessage(Run)
|
2005-05-18 07:32:09 +02:00
|
|
|
PositionMessage(Patrol)
|
|
|
|
PositionMessage(AddWaypoint)
|
2006-03-31 05:30:34 +02:00
|
|
|
PositionMessage(FormationGoto)
|
2006-05-04 09:40:31 +02:00
|
|
|
|
2006-02-22 23:45:16 +01:00
|
|
|
// NMT_Generic, target, action
|
2005-12-29 09:42:44 +01:00
|
|
|
EntityIntMessage(Generic)
|
2006-02-13 04:31:26 +01:00
|
|
|
EntityIntMessage(NotifyRequest)
|
2006-03-31 05:30:34 +02:00
|
|
|
EntityIntMessage(FormationGeneric)
|
2005-12-29 09:42:44 +01:00
|
|
|
|
2006-02-22 23:45:16 +01:00
|
|
|
// NMT_Produce, type, name
|
|
|
|
ProduceMessage(Produce)
|
|
|
|
|
2006-05-04 09:40:31 +02:00
|
|
|
// NMT_PlaceObject, template, x, y, z, angle, action
|
|
|
|
PlaceObjectMessage(PlaceObject)
|
|
|
|
|
2005-05-18 07:32:09 +02:00
|
|
|
default:
|
|
|
|
JS_ReportError(cx, "Invalid order type");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2006-03-31 05:30:34 +02:00
|
|
|
|
2006-07-06 05:17:44 +02:00
|
|
|
CNetMessage *CNetMessage::CreatePositionMessage( const CEntityList& entities, const int type, CVector2D pos )
|
2006-03-31 05:30:34 +02:00
|
|
|
{
|
|
|
|
#define PosMessage(_msg) \
|
|
|
|
case NMT_ ## _msg: \
|
|
|
|
{ \
|
|
|
|
C##_msg* msg = new C##_msg(); \
|
|
|
|
msg->m_Entities = entities; \
|
|
|
|
msg->m_TargetX = pos.x; \
|
|
|
|
msg->m_TargetY = pos.y; \
|
|
|
|
return msg; \
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
PosMessage(Goto)
|
|
|
|
PosMessage(Run)
|
|
|
|
PosMessage(Patrol)
|
|
|
|
PosMessage(AddWaypoint)
|
|
|
|
PosMessage(FormationGoto)
|
|
|
|
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2006-07-06 05:17:44 +02:00
|
|
|
CNetMessage *CNetMessage::CreateEntityIntMessage( const CEntityList& entities, const int type, HEntity& target, int action )
|
2006-03-31 05:30:34 +02:00
|
|
|
{
|
|
|
|
#define EntMessage(_msg) \
|
|
|
|
case NMT_ ## _msg: \
|
|
|
|
{ \
|
|
|
|
C##_msg* msg = new C##_msg(); \
|
|
|
|
msg->m_Entities = entities; \
|
|
|
|
msg->m_Target = target; \
|
|
|
|
msg->m_Action = action; \
|
|
|
|
return msg; \
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
EntMessage(Generic)
|
|
|
|
EntMessage(NotifyRequest)
|
|
|
|
EntMessage(FormationGeneric)
|
|
|
|
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2006-07-20 16:37:58 +02:00
|
|
|
CNetMessage *CNetMessage::CreateProduceMessage( const CEntityList& entities, const int type, int proType, const CStrW& name )
|
2006-03-31 05:30:34 +02:00
|
|
|
{
|
|
|
|
#define ProMessage(_msg)\
|
|
|
|
case NMT_ ## _msg: \
|
|
|
|
{ \
|
|
|
|
C##_msg* msg = new C##_msg(); \
|
|
|
|
msg->m_Entities = entities; \
|
|
|
|
msg->m_Type = proType; \
|
|
|
|
msg->m_Name = name; \
|
|
|
|
return msg; \
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
ProMessage(Produce)
|
|
|
|
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-10-20 03:06:43 +02:00
|
|
|
|