initial user message implementation with its natives and such

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40511
This commit is contained in:
Borja Ferrer 2007-02-16 18:47:16 +00:00
parent c91542fbe8
commit 0fbb38ef8e
9 changed files with 824 additions and 83 deletions

63
core/CMsgIdPool.h Normal file
View File

@ -0,0 +1,63 @@
/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_CMSGIDPOOL_H_
#define _INCLUDE_SOURCEMOD_CMSGIDPOOL_H_
#include "sm_trie.h"
#include "sourcemm_api.h"
#define INVALID_MESSAGE_ID -1
class CMessageIdPool
{
public:
CMessageIdPool()
{
m_Names = sm_trie_create();
}
~CMessageIdPool()
{
sm_trie_destroy(m_Names);
}
public:
int GetMessageId(const char *name)
{
int msgid;
if (!sm_trie_retrieve(m_Names, name, reinterpret_cast<void **>(&msgid)))
{
char buf[255];
int dummy;
msgid = 0;
while (gamedll->GetUserMessageInfo(msgid, buf, sizeof(buf), dummy))
{
if (strcmp(name, buf) == 0)
{
sm_trie_insert(m_Names, name, reinterpret_cast<void *>(msgid));
return msgid;
}
msgid++;
}
return INVALID_MESSAGE_ID;
}
return msgid;
}
private:
Trie *m_Names;
};
#endif //_INCLUDE_SOURCEMOD_CMSGIDPOOL_H_

View File

@ -0,0 +1,91 @@
/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
#define _INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_
#include <irecipientfilter.h>
#include <sp_vm_types.h>
class CellRecipientFilter : public IRecipientFilter
{
public:
CellRecipientFilter() : m_Reliable(false), m_InitMessage(false), m_Size(0), m_CellRecipients(NULL) {}
~CellRecipientFilter() {}
public: //IRecipientFilter
bool IsReliable() const;
bool IsInitMessage() const;
int GetRecipientCount() const;
int GetRecipientIndex(int slot) const;
public:
void SetRecipientPtr(cell_t *ptr, size_t count);
void SetReliable(bool isreliable);
void SetInitMessage(bool isinitmsg);
void ResetFilter();
private:
bool m_Reliable;
bool m_InitMessage;
size_t m_Size;
cell_t *m_CellRecipients;
};
inline void CellRecipientFilter::ResetFilter()
{
m_Reliable = false;
m_InitMessage = false;
m_Size = 0;
m_CellRecipients = NULL;
}
inline bool CellRecipientFilter::IsReliable() const
{
return m_Reliable;
}
inline bool CellRecipientFilter::IsInitMessage() const
{
return m_InitMessage;
}
inline int CellRecipientFilter::GetRecipientCount() const
{
return m_Size;
}
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
{
if ((slot < 0) || (slot >= GetRecipientCount()))
{
return -1;
}
return static_cast<int>(m_CellRecipients[slot]);
}
inline void CellRecipientFilter::SetInitMessage(bool isinitmsg)
{
m_InitMessage = isinitmsg;
}
inline void CellRecipientFilter::SetReliable(bool isreliable)
{
m_Reliable = isreliable;
}
inline void CellRecipientFilter::SetRecipientPtr(cell_t *ptr, size_t count)
{
m_CellRecipients = ptr;
m_Size = count;
}
#endif //_INCLUDE_SOURCEMOD_CELLRECIPIENTFILTER_H_

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="sourcemod_mm"
ProjectGUID="{E39527CD-7CAB-4420-97CC-DA1B93B260BC}"
RootNamespace="sourcemod_mm"
@ -269,10 +269,18 @@
RelativePath="..\CDbgReporter.h"
>
</File>
<File
RelativePath="..\CellRecipientFilter.h"
>
</File>
<File
RelativePath="..\CLogger.h"
>
</File>
<File
RelativePath="..\CMsgIdPool.h"
>
</File>
<File
RelativePath="..\CPlayerManager.h"
>
@ -633,6 +641,10 @@
RelativePath="..\smn_admin.cpp"
>
</File>
<File
RelativePath="..\smn_bitbuffer.cpp"
>
</File>
<File
RelativePath="..\smn_console.cpp"
>
@ -669,6 +681,10 @@
RelativePath="..\smn_textparse.cpp"
>
</File>
<File
RelativePath="..\smn_usermsgs.cpp"
>
</File>
</Filter>
</Files>
<Globals>

348
core/smn_bitbuffer.cpp Normal file
View File

@ -0,0 +1,348 @@
/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#include <bitbuf.h>
#include <vector.h>
#include "sourcemod.h"
#include "HandleSys.h"
static cell_t smn_BfWriteBool(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteOneBit(params[2]);
return 1;
}
static cell_t smn_BfWriteByte(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteByte(params[2]);
return 1;
}
static cell_t smn_BfWriteChar(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteChar(params[2]);
return 1;
}
static cell_t smn_BfWriteShort(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteShort(params[2]);
return 1;
}
static cell_t smn_BfWriteWord(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteWord(params[2]);
return 1;
}
static cell_t smn_BfWriteNum(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteLong(static_cast<long>(params[2]));
return 1;
}
static cell_t smn_BfWriteFloat(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteFloat(sp_ctof(params[2]));
return 1;
}
static cell_t smn_BfWriteString(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
int err;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
char *str;
if ((err=pCtx->LocalToString(params[2], &str)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
pBitBuf->WriteString(str);
return 1;
}
static cell_t smn_BfWriteEntity(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteShort(params[2]);
return 1;
}
static cell_t smn_BfWriteAngle(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteBitAngle(sp_ctof(params[2]), params[3]);
return 1;
}
static cell_t smn_BfWriteCoord(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
pBitBuf->WriteBitCoord(sp_ctof(params[2]));
return 1;
}
static cell_t smn_BfWriteVecCoord(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
cell_t *pVec;
pCtx->LocalToPhysAddr(params[2], &pVec);
Vector vec(sp_ctof(pVec[0]), sp_ctof(pVec[1]), sp_ctof(pVec[2]));
pBitBuf->WriteBitVec3Coord(vec);
return 1;
}
static cell_t smn_BfWriteVecNormal(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
cell_t *pVec;
pCtx->LocalToPhysAddr(params[2], &pVec);
Vector vec(sp_ctof(pVec[0]), sp_ctof(pVec[1]), sp_ctof(pVec[2]));
pBitBuf->WriteBitVec3Normal(vec);
return 1;
}
static cell_t smn_BfWriteAngles(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
bf_write *pBitBuf;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_WrBitBufType, &sec, (void **)&pBitBuf))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid bit buffer handle %x (error %d)", hndl, herr);
}
cell_t *pAng;
pCtx->LocalToPhysAddr(params[2], &pAng);
QAngle ang(sp_ctof(pAng[0]), sp_ctof(pAng[1]), sp_ctof(pAng[2]));
pBitBuf->WriteBitAngles(ang);
return 1;
}
REGISTER_NATIVES(wrbitbufnatives)
{
{"BfWriteBool", smn_BfWriteBool},
{"BfWriteByte", smn_BfWriteByte},
{"BfWriteChar", smn_BfWriteChar},
{"BfWriteShort", smn_BfWriteShort},
{"BfWriteWord", smn_BfWriteWord},
{"BfWriteNum", smn_BfWriteNum},
{"BfWriteFloat", smn_BfWriteFloat},
{"BfWriteString", smn_BfWriteString},
{"BfWriteEntity", smn_BfWriteEntity},
{"BfWriteAngle", smn_BfWriteAngle},
{"BfWriteCoord", smn_BfWriteCoord},
{"BfWriteVecCoord", smn_BfWriteVecCoord},
{"BfWriteVecNormal", smn_BfWriteVecNormal},
{"BfWriteAngles", smn_BfWriteAngles},
{NULL, NULL}
};

190
core/smn_usermsgs.cpp Normal file
View File

@ -0,0 +1,190 @@
/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#include "HandleSys.h"
#include "CellRecipientFilter.h"
#include "CMsgIdPool.h"
#define USERMSG_PASSTHRU (1<<0)
#define USERMSG_PASSTHRU_ALL (1<<1)
#define USERMSG_RELIABLE (1<<2)
#define USERMSG_INITMSG (1<<3)
CMessageIdPool g_MessageIds;
CellRecipientFilter g_MsgRecFilter;
HandleType_t g_WrBitBufType;
Handle_t g_CurMsgHandle;
bool g_IsMsgInExec = false;
int g_CurMsgFlags = 0;
class UsrMessageNatives :
public SMGlobalClass,
public IHandleTypeDispatch
{
public:
void OnSourceModAllInitialized()
{
g_WrBitBufType = g_HandleSys.CreateType("BitBufWriter", this, 0, NULL, NULL, g_pCoreIdent, NULL);
}
void OnSourceModShutdown()
{
g_HandleSys.RemoveType(g_WrBitBufType, g_pCoreIdent);
g_WrBitBufType = 0;
}
void OnHandleDestroy(HandleType_t type, void *object)
{
}
};
static cell_t smn_GetUserMessageId(IPluginContext *pCtx, const cell_t *params)
{
char *msgname;
int err;
if ((err=pCtx->LocalToString(params[1], &msgname)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
return g_MessageIds.GetMessageId(msgname);
}
static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
{
char *msgname;
cell_t *cl_array;
int msgid, err;
bf_write *pBitBuf;
if (g_IsMsgInExec)
{
return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
}
if ((err=pCtx->LocalToString(params[1], &msgname)) != SP_ERROR_NONE)
{
pCtx->ThrowNativeErrorEx(err, NULL);
return 0;
}
if ((msgid=g_MessageIds.GetMessageId(msgname)) == INVALID_MESSAGE_ID)
{
return pCtx->ThrowNativeError("Invalid message name: \"%s\"", msgname);
}
pCtx->LocalToPhysAddr(params[2], &cl_array);
g_CurMsgFlags = params[4];
g_MsgRecFilter.SetRecipientPtr(cl_array, params[3]);
if (g_CurMsgFlags & USERMSG_INITMSG)
{
g_MsgRecFilter.SetInitMessage(true);
}
if (g_CurMsgFlags & USERMSG_RELIABLE)
{
g_MsgRecFilter.SetReliable(true);
}
if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU)) //:TODO: change this when we can hook messages
{
pBitBuf = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
} else {
pBitBuf = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
}
g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
g_IsMsgInExec = true;
return g_CurMsgHandle;
}
static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
{
cell_t *cl_array;
bf_write *pBitBuf;
int msgid = params[1];
if (g_IsMsgInExec)
{
return pCtx->ThrowNativeError("Unable to execute a new message, there is already one in progress");
}
if (msgid < 0 || msgid > 255)
{
return pCtx->ThrowNativeError("Invalid message id supplied (%d)", msgid);
}
pCtx->LocalToPhysAddr(params[2], &cl_array);
g_CurMsgFlags = params[4];
g_MsgRecFilter.SetRecipientPtr(cl_array, params[3]);
if (g_CurMsgFlags & USERMSG_INITMSG)
{
g_MsgRecFilter.SetInitMessage(true);
}
if (g_CurMsgFlags & USERMSG_RELIABLE)
{
g_MsgRecFilter.SetReliable(true);
}
if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU)) //:TODO: change this when we can hook messages
{
pBitBuf = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
} else {
pBitBuf = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&g_MsgRecFilter), msgid);
}
g_CurMsgHandle = g_HandleSys.CreateHandle(g_WrBitBufType, pBitBuf, pCtx->GetIdentity(), g_pCoreIdent, NULL);
g_IsMsgInExec = true;
return g_CurMsgHandle;
}
static cell_t smn_EndMessage(IPluginContext *pCtx, const cell_t *params)
{
HandleSecurity sec;
if (!g_IsMsgInExec)
{
return pCtx->ThrowNativeError("Unable to end message, no message is in progress");
}
if (g_CurMsgFlags & (USERMSG_PASSTHRU_ALL|USERMSG_PASSTHRU))
{
engine->MessageEnd();
} else {
ENGINE_CALL(MessageEnd)();
}
sec.pOwner = pCtx->GetIdentity();
sec.pIdentity = g_pCoreIdent;
g_HandleSys.FreeHandle(g_CurMsgHandle, &sec);
g_IsMsgInExec = false;
g_CurMsgFlags = 0;
g_MsgRecFilter.ResetFilter();
return 1;
}
static UsrMessageNatives s_UsrMessageNatives;
REGISTER_NATIVES(usrmsgnatives)
{
{"GetUserMessageId", smn_GetUserMessageId},
{"StartMessage", smn_StartMessage},
{"StartMessageEx", smn_StartMessageEx},
{"EndMessage", smn_EndMessage},
{NULL, NULL}
};

View File

@ -101,5 +101,6 @@ private:
};
extern SourceModBase g_SourceMod;
extern HandleType_t g_WrBitBufType;
#endif //_INCLUDE_SOURCEMOD_GLOBALHEADER_H_

View File

@ -12,49 +12,11 @@
*
* Version: $Id$
*/
#if defined _eventsmsgs_included
#if defined _bitbuffer_included
#endinput
#endif
#define _eventsmsgs_included
enum UserMsg
{
INVALID_MESSAGE_ID = -1,
};
#define USERMSG_PASSTHRU (1<<0) /**< Message will pass through other SourceMM plugins */
#define USERMSG_PASSTHRU_ALL (1<<1) /**< Message will pass through other SourceMM plugins AND SourceMod */
//:NOTE: none of this is implemented yet, remove this notice and add to sourcemod.inc once it's done!
//:NOTE: for DS, add main event natives below EndMessage but above bf_ stuff
/**
* Returns the ID of a given message, or -1 on failure.
*
* @param msg String containing message name (case sensitive).
* @return A message index, or INVALID_MESSAGE_ID on failure.
*/
native UserMsg:GetUserMessageId(const String:msg[]);
/**
* Starts a usermessage (network message).
* @note Only one message can be active at a time.
*
* @param msg Message index to start.
* @param clients Array containing player indexes to broadcast to.
* @param numClients Number of players in the array.
* @return A handle to a bf_write bit packing structure, or
* INVALID_HANDLE on failure.
*/
native Handle:StartMessage(UserMsg:msg, clients[], numClients, flags);
/**
* Ends a previously started user message (network message).
*
* @noreturn
*/
native EndMessage();
#define _bitbuffer_included
/**
* Writes a single bit to a writable bitbuffer (bf_write).
@ -197,44 +159,3 @@ native BfWriteVecNormal(Handle:bf, Float:vec[3]);
* @error Invalid or incorrect Handle.
*/
native BfWriteAngles(Handle:bf, Float:angles[3]);
/**
* Starts a usermessage (network message) that broadcasts to all clients.
*
* @param msg Message index to start.
* @param flags Optional flags to set.
* @return A handle to a bf_write bit packing structure, or
* INVALID_HANDLE on failure.
*/
stock Handle:StartMessageAll(UserMsg:msg, flags=0)
{
new maxClients = GetMaxClients();
new total = 0;
new clients[maxClients];
for (new i=1; i<=maxClients; i++)
{
if (IsClientConnected(i))
{
clients[total++] = i;
}
}
return StartMessage(msg, clients, total, flags);
}
/**
* Starts a simpler usermessage (network message) for one client.
*
* @param msg Message index to start.
* @param client Client to send to.
* @param flags Optional flags to set.
* @return A handle to a bf_write bit packing structure, or
* INVALID_HANDLE on failure.
*/
stock Handle:StartMessageOne(UserMsg:msg, client, flags=0)
{
new players[1];
players[0] = client;
return StartMsesage(msg, players, 1, flags);
}

View File

@ -34,6 +34,8 @@ struct Plugin
#include <admin>
#include <files>
#include <console>
#include <usermessages>
#include <bitbuffer>
/**
* Declare this as a struct in your plugin to expose its information.

View File

@ -0,0 +1,109 @@
/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is part of the SourceMod/SourcePawn SDK. This file may only be used
* or modified under the Terms and Conditions of its License Agreement, which is found
* in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins
* may change at any time. To view the latest information, see:
* http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#if defined _eventsmsgs_included
#endinput
#endif
#define _eventsmsgs_included
enum UserMsg
{
INVALID_MESSAGE_ID = -1,
};
#define USERMSG_PASSTHRU (1<<0) /**< Message will pass through other SourceMM plugins */
#define USERMSG_PASSTHRU_ALL (1<<1) /**< Message will pass through other SourceMM plugins AND SourceMod */
#define USERMSG_RELIABLE (1<<2) /**< Message will be set to reliable */
#define USERMSG_INITMSG (1<<3) /**< Message will be considered to be an initmsg */
/**
* Returns the ID of a given message, or -1 on failure.
*
* @param msg String containing message name (case sensitive).
* @return A message index, or INVALID_MESSAGE_ID on failure.
*/
native UserMsg:GetUserMessageId(const String:msg[]);
/**
* Starts a usermessage (network message).
* @note Only one message can be active at a time.
*
* @param msgname Message name to start.
* @param clients Array containing player indexes to broadcast to.
* @param numClients Number of players in the array.
* @return A handle to a bf_write bit packing structure, or
* INVALID_HANDLE on failure.
*/
native Handle:StartMessage(String:msgname[], clients[], numClients, flags);
/**
* Starts a usermessage (network message).
* @note Only one message can be active at a time.
*
* @param msg Message index to start.
* @param clients Array containing player indexes to broadcast to.
* @param numClients Number of players in the array.
* @return A handle to a bf_write bit packing structure, or
* INVALID_HANDLE on failure.
*/
native Handle:StartMessageEx(UserMsg:msg, clients[], numClients, flags);
/**
* Ends a previously started user message (network message).
*
* @noreturn
*/
native EndMessage();
/**
* Starts a usermessage (network message) that broadcasts to all clients.
*
* @param msgname Message name to start.
* @param flags Optional flags to set.
* @return A handle to a bf_write bit packing structure, or
* INVALID_HANDLE on failure.
*/
stock Handle:StartMessageAll(String:msgname[], flags=0)
{
new maxClients = GetMaxClients();
new total = 0;
new clients[maxClients];
for (new i=1; i<=maxClients; i++)
{
if (IsClientConnected(i))
{
clients[total++] = i;
}
}
return StartMessage(msgname, clients, total, flags);
}
/**
* Starts a simpler usermessage (network message) for one client.
*
* @param msgname Message name to start.
* @param client Client to send to.
* @param flags Optional flags to set.
* @return A handle to a bf_write bit packing structure, or
* INVALID_HANDLE on failure.
*/
stock Handle:StartMessageOne(String:msgname[], client, flags=0)
{
new players[1];
players[0] = client;
return StartMessage(msgname, players, 1, flags);
}