core/smn_protobuf.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Tue Jan 22 21:43:12 2013 -0500 (2013-01-22)
changeset 3743 a98686a77974
child 3747 cb3f97a59d55
permissions -rw-r--r--
Added initial support for protobuf usermessages on CS:GO (bug 5579, r=asherkin).
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2013 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "UserMessages.h"
    33 
    34 #ifdef USE_PROTOBUF_USERMESSAGES
    35 
    36 #include "HandleSys.h"
    37 #include "UserMessagePBHelpers.h"
    38 #include "smn_usermsgs.h"
    39 
    40 // Assumes pbuf message handle is param 1, gets message as msg
    41 #define GET_MSG_FROM_HANDLE_OR_ERR()                  \
    42 	Handle_t hndl = static_cast<Handle_t>(params[1]); \
    43 	HandleError herr;                                 \
    44 	HandleSecurity sec;                               \
    45 	SMProtobufMessage *msg;                           \
    46 	                                                  \
    47 	sec.pOwner = NULL;                                \
    48 	sec.pIdentity = g_pCoreIdent;                     \
    49 	                                                  \
    50 	if ((herr=g_HandleSys.ReadHandle(hndl, g_ProtobufType, &sec, (void **)&msg)) \
    51 		!= HandleError_None)                          \
    52 	{                                                 \
    53 		return pCtx->ThrowNativeError("Invalid protobuf message handle %x (error %d)", hndl, herr); \
    54 	}
    55 
    56 // Assumes message field name is param 2, gets as strField
    57 #define GET_FIELD_NAME_OR_ERR()                                           \
    58 	int err;                                                              \
    59 	char *strField;                                                       \
    60 	if ((err=pCtx->LocalToString(params[2], &strField)) != SP_ERROR_NONE) \
    61 	{                                                                     \
    62 		pCtx->ThrowNativeErrorEx(err, NULL);                              \
    63 		return 0;                                                         \
    64 	}
    65 
    66 static cell_t smn_PbReadInt(IPluginContext *pCtx, const cell_t *params)
    67 {
    68 	GET_MSG_FROM_HANDLE_OR_ERR();
    69 	GET_FIELD_NAME_OR_ERR();
    70 
    71 	int ret;
    72 	if (!msg->GetInt32OrUnsigned(strField, &ret))
    73 	{
    74 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
    75 	}
    76 
    77 	return ret;
    78 }
    79 
    80 static cell_t smn_PbReadFloat(IPluginContext *pCtx, const cell_t *params)
    81 {
    82 	GET_MSG_FROM_HANDLE_OR_ERR();
    83 	GET_FIELD_NAME_OR_ERR();
    84 
    85 	float ret;
    86 	if (!msg->GetFloatOrDouble(strField, &ret))
    87 	{
    88 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
    89 	}
    90 
    91 	return sp_ftoc(ret);
    92 }
    93 
    94 static cell_t smn_PbReadBool(IPluginContext *pCtx, const cell_t *params)
    95 {
    96 	GET_MSG_FROM_HANDLE_OR_ERR();
    97 	GET_FIELD_NAME_OR_ERR();
    98 
    99 	bool ret;
   100 	if (!msg->GetBool(strField, &ret))
   101 	{
   102 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   103 	}
   104 
   105 	return ret ? 1 : 0;
   106 }
   107 
   108 static cell_t smn_PbReadString(IPluginContext *pCtx, const cell_t *params)
   109 {
   110 	GET_MSG_FROM_HANDLE_OR_ERR();
   111 	GET_FIELD_NAME_OR_ERR();
   112 
   113 	char *buf;
   114 	pCtx->LocalToPhysAddr(params[3], (cell_t **)&buf);
   115 
   116 	if (!msg->GetString(strField, buf, params[4]))
   117 	{
   118 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   119 	}
   120 
   121 	return 1;
   122 }
   123 
   124 static cell_t smn_PbReadColor(IPluginContext *pCtx, const cell_t *params)
   125 {
   126 	GET_MSG_FROM_HANDLE_OR_ERR();
   127 	GET_FIELD_NAME_OR_ERR();
   128 
   129 	cell_t *out;
   130 	pCtx->LocalToPhysAddr(params[3], &out);
   131 
   132 	Color clr;
   133 	if (!msg->GetColor(strField, &clr))
   134 	{
   135 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   136 	}
   137 
   138 	out[0] = clr.r();
   139 	out[1] = clr.g();
   140 	out[2] = clr.b();
   141 	out[3] = clr.a();
   142 
   143 	return 1;
   144 }
   145 
   146 static cell_t smn_PbReadAngle(IPluginContext *pCtx, const cell_t *params)
   147 {
   148 	GET_MSG_FROM_HANDLE_OR_ERR();
   149 	GET_FIELD_NAME_OR_ERR();
   150 
   151 	cell_t *out;
   152 	pCtx->LocalToPhysAddr(params[3], &out);
   153 
   154 	QAngle ang;
   155 	if (!msg->GetQAngle(strField, &ang))
   156 	{
   157 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   158 	}
   159 
   160 	out[0] = sp_ftoc(ang.x);
   161 	out[1] = sp_ftoc(ang.y);
   162 	out[2] = sp_ftoc(ang.z);
   163 
   164 	return 1;
   165 }
   166 
   167 static cell_t smn_PbReadVector(IPluginContext *pCtx, const cell_t *params)
   168 {
   169 	GET_MSG_FROM_HANDLE_OR_ERR();
   170 	GET_FIELD_NAME_OR_ERR();
   171 
   172 	cell_t *out;
   173 	pCtx->LocalToPhysAddr(params[3], &out);
   174 
   175 	Vector vec;
   176 	if (!msg->GetVector(strField, &vec))
   177 	{
   178 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   179 	}
   180 
   181 	out[0] = sp_ftoc(vec.x);
   182 	out[1] = sp_ftoc(vec.y);
   183 	out[2] = sp_ftoc(vec.z);
   184 
   185 	return 1;
   186 }
   187 
   188 static cell_t smn_PbReadVector2D(IPluginContext *pCtx, const cell_t *params)
   189 {
   190 	GET_MSG_FROM_HANDLE_OR_ERR();
   191 	GET_FIELD_NAME_OR_ERR();
   192 
   193 	cell_t *out;
   194 	pCtx->LocalToPhysAddr(params[3], &out);
   195 
   196 	Vector2D vec;
   197 	if (!msg->GetVector2D(strField, &vec))
   198 	{
   199 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   200 	}
   201 
   202 	out[0] = sp_ftoc(vec.x);
   203 	out[1] = sp_ftoc(vec.y);
   204 
   205 	return 1;
   206 }
   207 
   208 static cell_t smn_PbGetRepeatedFieldCount(IPluginContext *pCtx, const cell_t *params)
   209 {
   210 	GET_MSG_FROM_HANDLE_OR_ERR();
   211 	GET_FIELD_NAME_OR_ERR();
   212 
   213 	int cnt = msg->GetRepeatedFieldCount(strField);
   214 	if (cnt == -1)
   215 	{
   216 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   217 	}
   218 
   219 	return cnt;
   220 }
   221 
   222 static cell_t smn_PbReadRepeatedInt(IPluginContext *pCtx, const cell_t *params)
   223 {
   224 	GET_MSG_FROM_HANDLE_OR_ERR();
   225 	GET_FIELD_NAME_OR_ERR();
   226 
   227 	int ret;
   228 	if (!msg->GetRepeatedInt32OrUnsigned(strField, params[3], &ret))
   229 	{
   230 		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
   231 	}
   232 
   233 	return ret;
   234 }
   235 
   236 static cell_t smn_PbReadRepeatedFloat(IPluginContext *pCtx, const cell_t *params)
   237 {
   238 	GET_MSG_FROM_HANDLE_OR_ERR();
   239 	GET_FIELD_NAME_OR_ERR();
   240 
   241 	float ret;
   242 	if (!msg->GetRepeatedFloatOrDouble(strField, params[3], &ret))
   243 	{
   244 		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
   245 	}
   246 
   247 	return sp_ftoc(ret);
   248 }
   249 
   250 static cell_t smn_PbReadRepeatedBool(IPluginContext *pCtx, const cell_t *params)
   251 {
   252 	GET_MSG_FROM_HANDLE_OR_ERR();
   253 	GET_FIELD_NAME_OR_ERR();
   254 
   255 	bool ret;
   256 	if (!msg->GetRepeatedBool(strField, params[3], &ret))
   257 	{
   258 		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
   259 	}
   260 
   261 	return ret ? 1 : 0;
   262 }
   263 
   264 static cell_t smn_PbReadRepeatedString(IPluginContext *pCtx, const cell_t *params)
   265 {
   266 	GET_MSG_FROM_HANDLE_OR_ERR();
   267 	GET_FIELD_NAME_OR_ERR();
   268 
   269 	char *buf;
   270 	pCtx->LocalToPhysAddr(params[4], (cell_t **)&buf);
   271 
   272 	if (!msg->GetRepeatedString(strField, params[3], buf, params[5]))
   273 	{
   274 		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
   275 	}
   276 
   277 	return 1;
   278 }
   279 
   280 static cell_t smn_PbReadRepeatedColor(IPluginContext *pCtx, const cell_t *params)
   281 {
   282 	GET_MSG_FROM_HANDLE_OR_ERR();
   283 	GET_FIELD_NAME_OR_ERR();
   284 
   285 	cell_t *out;
   286 	pCtx->LocalToPhysAddr(params[4], &out);
   287 
   288 	Color clr;
   289 	if (!msg->GetRepeatedColor(strField, params[3], &clr))
   290 	{
   291 		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
   292 	}
   293 
   294 	out[0] = clr.r();
   295 	out[1] = clr.g();
   296 	out[2] = clr.b();
   297 	out[3] = clr.a();
   298 
   299 	return 1;
   300 }
   301 
   302 static cell_t smn_PbReadRepeatedAngle(IPluginContext *pCtx, const cell_t *params)
   303 {
   304 	GET_MSG_FROM_HANDLE_OR_ERR();
   305 	GET_FIELD_NAME_OR_ERR();
   306 
   307 	cell_t *out;
   308 	pCtx->LocalToPhysAddr(params[4], &out);
   309 
   310 	QAngle ang;
   311 	if (!msg->GetRepeatedQAngle(strField, params[3], &ang))
   312 	{
   313 		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
   314 	}
   315 
   316 	out[0] = sp_ftoc(ang.x);
   317 	out[1] = sp_ftoc(ang.y);
   318 	out[2] = sp_ftoc(ang.z);
   319 
   320 	return 1;
   321 }
   322 
   323 static cell_t smn_PbReadRepeatedVector(IPluginContext *pCtx, const cell_t *params)
   324 {
   325 	GET_MSG_FROM_HANDLE_OR_ERR();
   326 	GET_FIELD_NAME_OR_ERR();
   327 
   328 	cell_t *out;
   329 	pCtx->LocalToPhysAddr(params[4], &out);
   330 
   331 	Vector vec;
   332 	if (!msg->GetRepeatedVector(strField, params[3], &vec))
   333 	{
   334 		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
   335 	}
   336 
   337 	out[0] = sp_ftoc(vec.x);
   338 	out[1] = sp_ftoc(vec.y);
   339 	out[2] = sp_ftoc(vec.z);
   340 
   341 	return 1;
   342 }
   343 
   344 static cell_t smn_PbReadRepeatedVector2D(IPluginContext *pCtx, const cell_t *params)
   345 {
   346 	GET_MSG_FROM_HANDLE_OR_ERR();
   347 	GET_FIELD_NAME_OR_ERR();
   348 
   349 	cell_t *out;
   350 	pCtx->LocalToPhysAddr(params[4], &out);
   351 
   352 	Vector2D vec;
   353 	if (!msg->GetRepeatedVector2D(strField, params[3], &vec))
   354 	{
   355 		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
   356 	}
   357 
   358 	out[0] = sp_ftoc(vec.x);
   359 	out[1] = sp_ftoc(vec.y);
   360 
   361 	return 1;
   362 }
   363 
   364 static cell_t smn_PbSetInt(IPluginContext *pCtx, const cell_t *params)
   365 {
   366 	GET_MSG_FROM_HANDLE_OR_ERR();
   367 	GET_FIELD_NAME_OR_ERR();
   368 
   369 	if (!msg->SetInt32OrUnsigned(strField, params[3]))
   370 	{
   371 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   372 	}
   373 
   374 	return 1;
   375 }
   376 
   377 static cell_t smn_PbSetFloat(IPluginContext *pCtx, const cell_t *params)
   378 {
   379 	GET_MSG_FROM_HANDLE_OR_ERR();
   380 	GET_FIELD_NAME_OR_ERR();
   381 
   382 	if (!msg->SetFloatOrDouble(strField, sp_ctof(params[3])))
   383 	{
   384 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   385 	}
   386 
   387 	return 1;
   388 }
   389 
   390 static cell_t smn_PbSetBool(IPluginContext *pCtx, const cell_t *params)
   391 {
   392 	GET_MSG_FROM_HANDLE_OR_ERR();
   393 	GET_FIELD_NAME_OR_ERR();
   394 
   395 	bool value = (params[3] == 0 ? false : true);
   396 	if (!msg->SetBool(strField, value))
   397 	{
   398 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   399 	}
   400 
   401 	return 1;
   402 }
   403 
   404 static cell_t smn_PbSetString(IPluginContext *pCtx, const cell_t *params)
   405 {
   406 	GET_MSG_FROM_HANDLE_OR_ERR();
   407 	GET_FIELD_NAME_OR_ERR();
   408 
   409 	char *strValue;
   410 	if ((err=pCtx->LocalToString(params[3], &strValue)) != SP_ERROR_NONE)
   411 	{
   412 		pCtx->ThrowNativeErrorEx(err, NULL);
   413 		return 0;
   414 	}
   415 
   416 	if (!msg->SetString(strField, strValue))
   417 	{
   418 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   419 	}
   420 
   421 	return 1;
   422 }
   423 
   424 static cell_t smn_PbSetColor(IPluginContext *pCtx, const cell_t *params)
   425 {
   426 	GET_MSG_FROM_HANDLE_OR_ERR();
   427 	GET_FIELD_NAME_OR_ERR();
   428 
   429 	cell_t *clrParams;
   430 	if ((err=pCtx->LocalToPhysAddr(params[3], &clrParams)) != SP_ERROR_NONE)
   431 	{
   432 		pCtx->ThrowNativeErrorEx(err, NULL);
   433 		return 0;
   434 	}
   435 
   436 	Color clr(
   437 		clrParams[0],
   438 		clrParams[1],
   439 		clrParams[2],
   440 		clrParams[3]);
   441 
   442 	if (!msg->SetColor(strField, clr))
   443 	{
   444 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   445 	}
   446 
   447 	return 1;
   448 }
   449 
   450 static cell_t smn_PbSetAngle(IPluginContext *pCtx, const cell_t *params)
   451 {
   452 	GET_MSG_FROM_HANDLE_OR_ERR();
   453 	GET_FIELD_NAME_OR_ERR();
   454 
   455 	cell_t *angParams;
   456 	if ((err=pCtx->LocalToPhysAddr(params[3], &angParams)) != SP_ERROR_NONE)
   457 	{
   458 		pCtx->ThrowNativeErrorEx(err, NULL);
   459 		return 0;
   460 	}
   461 
   462 	QAngle ang(
   463 		sp_ctof(angParams[0]),
   464 		sp_ctof(angParams[1]),
   465 		sp_ctof(angParams[2]));
   466 
   467 	if (!msg->SetQAngle(strField, ang))
   468 	{
   469 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   470 	}
   471 
   472 	return 1;
   473 }
   474 
   475 static cell_t smn_PbSetVector(IPluginContext *pCtx, const cell_t *params)
   476 {
   477 	GET_MSG_FROM_HANDLE_OR_ERR();
   478 	GET_FIELD_NAME_OR_ERR();
   479 
   480 	cell_t *vecParams;
   481 	if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
   482 	{
   483 		pCtx->ThrowNativeErrorEx(err, NULL);
   484 		return 0;
   485 	}
   486 
   487 	Vector vec(
   488 		sp_ctof(vecParams[0]),
   489 		sp_ctof(vecParams[1]),
   490 		sp_ctof(vecParams[2]));
   491 
   492 	if (!msg->SetVector(strField, vec))
   493 	{
   494 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   495 	}
   496 
   497 	return 1;
   498 }
   499 
   500 static cell_t smn_PbSetVector2D(IPluginContext *pCtx, const cell_t *params)
   501 {
   502 	GET_MSG_FROM_HANDLE_OR_ERR();
   503 	GET_FIELD_NAME_OR_ERR();
   504 
   505 	cell_t *vecParams;
   506 	if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
   507 	{
   508 		pCtx->ThrowNativeErrorEx(err, NULL);
   509 		return 0;
   510 	}
   511 
   512 	Vector2D vec(
   513 		sp_ctof(vecParams[0]),
   514 		sp_ctof(vecParams[1]));
   515 
   516 	if (!msg->SetVector2D(strField, vec))
   517 	{
   518 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   519 	}
   520 
   521 	return 1;
   522 }
   523 
   524 static cell_t smn_PbAddInt(IPluginContext *pCtx, const cell_t *params)
   525 {
   526 	GET_MSG_FROM_HANDLE_OR_ERR();
   527 	GET_FIELD_NAME_OR_ERR();
   528 
   529 	if (!msg->AddInt32OrUnsigned(strField, params[3]))
   530 	{
   531 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   532 	}
   533 
   534 	return 1;
   535 }
   536 
   537 static cell_t smn_PbAddFloat(IPluginContext *pCtx, const cell_t *params)
   538 {
   539 	GET_MSG_FROM_HANDLE_OR_ERR();
   540 	GET_FIELD_NAME_OR_ERR();
   541 
   542 	if (!msg->AddFloatOrDouble(strField, sp_ctof(params[3])))
   543 	{
   544 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   545 	}
   546 
   547 	return 1;
   548 }
   549 
   550 static cell_t smn_PbAddBool(IPluginContext *pCtx, const cell_t *params)
   551 {
   552 	GET_MSG_FROM_HANDLE_OR_ERR();
   553 	GET_FIELD_NAME_OR_ERR();
   554 
   555 	bool value = (params[3] == 0 ? false : true);
   556 	if (!msg->AddBool(strField, value))
   557 	{
   558 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   559 	}
   560 
   561 	return 1;
   562 }
   563 
   564 static cell_t smn_PbAddString(IPluginContext *pCtx, const cell_t *params)
   565 {
   566 	GET_MSG_FROM_HANDLE_OR_ERR();
   567 	GET_FIELD_NAME_OR_ERR();
   568 
   569 	char *strValue;
   570 	if ((err=pCtx->LocalToString(params[3], &strValue)) != SP_ERROR_NONE)
   571 	{
   572 		pCtx->ThrowNativeErrorEx(err, NULL);
   573 		return 0;
   574 	}
   575 
   576 	if (!msg->AddString(strField, strValue))
   577 	{
   578 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   579 	}
   580 
   581 	return 1;
   582 }
   583 
   584 static cell_t smn_PbAddColor(IPluginContext *pCtx, const cell_t *params)
   585 {
   586 	GET_MSG_FROM_HANDLE_OR_ERR();
   587 	GET_FIELD_NAME_OR_ERR();
   588 
   589 	cell_t *clrParams;
   590 	if ((err=pCtx->LocalToPhysAddr(params[3], &clrParams)) != SP_ERROR_NONE)
   591 	{
   592 		pCtx->ThrowNativeErrorEx(err, NULL);
   593 		return 0;
   594 	}
   595 
   596 	Color clr(
   597 		clrParams[0],
   598 		clrParams[1],
   599 		clrParams[2],
   600 		clrParams[3]);
   601 
   602 	if (!msg->AddColor(strField, clr))
   603 	{
   604 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   605 	}
   606 
   607 	return 1;
   608 }
   609 
   610 static cell_t smn_PbAddAngle(IPluginContext *pCtx, const cell_t *params)
   611 {
   612 	GET_MSG_FROM_HANDLE_OR_ERR();
   613 	GET_FIELD_NAME_OR_ERR();
   614 
   615 	cell_t *angParams;
   616 	if ((err=pCtx->LocalToPhysAddr(params[3], &angParams)) != SP_ERROR_NONE)
   617 	{
   618 		pCtx->ThrowNativeErrorEx(err, NULL);
   619 		return 0;
   620 	}
   621 
   622 	QAngle ang(
   623 		sp_ctof(angParams[0]),
   624 		sp_ctof(angParams[1]),
   625 		sp_ctof(angParams[2]));
   626 
   627 	if (!msg->AddQAngle(strField, ang))
   628 	{
   629 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   630 	}
   631 
   632 	return 1;
   633 }
   634 
   635 static cell_t smn_PbAddVector(IPluginContext *pCtx, const cell_t *params)
   636 {
   637 	GET_MSG_FROM_HANDLE_OR_ERR();
   638 	GET_FIELD_NAME_OR_ERR();
   639 
   640 	cell_t *vecParams;
   641 	if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
   642 	{
   643 		pCtx->ThrowNativeErrorEx(err, NULL);
   644 		return 0;
   645 	}
   646 
   647 	Vector vec(
   648 		sp_ctof(vecParams[0]),
   649 		sp_ctof(vecParams[1]),
   650 		sp_ctof(vecParams[2]));
   651 
   652 	if (!msg->AddVector(strField, vec))
   653 	{
   654 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   655 	}
   656 
   657 	return 1;
   658 }
   659 
   660 static cell_t smn_PbAddVector2D(IPluginContext *pCtx, const cell_t *params)
   661 {
   662 	GET_MSG_FROM_HANDLE_OR_ERR();
   663 	GET_FIELD_NAME_OR_ERR();
   664 
   665 	cell_t *vecParams;
   666 	if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE)
   667 	{
   668 		pCtx->ThrowNativeErrorEx(err, NULL);
   669 		return 0;
   670 	}
   671 
   672 	Vector2D vec(
   673 		sp_ctof(vecParams[0]),
   674 		sp_ctof(vecParams[1]));
   675 
   676 	if (!msg->AddVector2D(strField, vec))
   677 	{
   678 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   679 	}
   680 
   681 	return 1;
   682 }
   683 
   684 static cell_t smn_PbReadMessage(IPluginContext *pCtx, const cell_t *params)
   685 {
   686 	GET_MSG_FROM_HANDLE_OR_ERR();
   687 	GET_FIELD_NAME_OR_ERR();
   688 
   689 	protobuf::Message *innerMsg;
   690 	if (!msg->GetMessage(strField, &innerMsg))
   691 	{
   692 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   693 	}
   694 
   695 	Handle_t outHndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(innerMsg), NULL, g_pCoreIdent, NULL);
   696 	msg->AddChildHandle(outHndl);
   697 
   698 	return outHndl;
   699 }
   700 
   701 static cell_t smn_PbReadRepeatedMessage(IPluginContext *pCtx, const cell_t *params)
   702 {
   703 	GET_MSG_FROM_HANDLE_OR_ERR();
   704 	GET_FIELD_NAME_OR_ERR();
   705 
   706 	const protobuf::Message *innerMsg;
   707 	if (!msg->GetRepeatedMessage(strField, params[3], &innerMsg))
   708 	{
   709 		return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[3], msg->GetProtobufMessage()->GetTypeName());
   710 	}
   711 
   712 	Handle_t outHndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(const_cast<protobuf::Message *>(innerMsg)), NULL, g_pCoreIdent, NULL);
   713 	msg->AddChildHandle(outHndl);
   714 
   715 	return outHndl;
   716 }
   717 
   718 static cell_t smn_PbAddMessage(IPluginContext *pCtx, const cell_t *params)
   719 {
   720 	GET_MSG_FROM_HANDLE_OR_ERR();
   721 	GET_FIELD_NAME_OR_ERR();
   722 
   723 	protobuf::Message *innerMsg;
   724 	if (!msg->AddMessage(strField, &innerMsg))
   725 	{
   726 		return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName());
   727 	}
   728 
   729 	Handle_t outHndl = g_HandleSys.CreateHandle(g_ProtobufType, new SMProtobufMessage(innerMsg), NULL, g_pCoreIdent, NULL);
   730 	msg->AddChildHandle(outHndl);
   731 
   732 	return outHndl;
   733 }
   734 
   735 REGISTER_NATIVES(protobufnatives)
   736 {
   737 	{"PbReadInt",					smn_PbReadInt},
   738 	{"PbReadFloat",					smn_PbReadFloat},
   739 	{"PbReadBool",					smn_PbReadBool},
   740 	{"PbReadString",				smn_PbReadString},
   741 	{"PbReadColor",					smn_PbReadColor},
   742 	{"PbReadAngle",					smn_PbReadAngle},
   743 	{"PbReadVector",				smn_PbReadVector},
   744 	{"PbReadVector2D",				smn_PbReadVector2D},
   745 	{"PbGetRepeatedFieldCount",		smn_PbGetRepeatedFieldCount},
   746 	{"PbReadRepeatedInt",			smn_PbReadRepeatedInt},
   747 	{"PbReadRepeatedFloat",			smn_PbReadRepeatedFloat},
   748 	{"PbReadRepeatedBool",			smn_PbReadRepeatedBool},
   749 	{"PbReadRepeatedString",		smn_PbReadRepeatedString},
   750 	{"PbReadRepeatedColor",			smn_PbReadRepeatedColor},
   751 	{"PbReadRepeatedAngle",			smn_PbReadRepeatedAngle},
   752 	{"PbReadRepeatedVector",		smn_PbReadRepeatedVector},
   753 	{"PbReadRepeatedVector2D",		smn_PbReadRepeatedVector2D},
   754 	{"PbSetInt",					smn_PbSetInt},
   755 	{"PbSetFloat",					smn_PbSetFloat},
   756 	{"PbSetBool",					smn_PbSetBool},
   757 	{"PbSetString",					smn_PbSetString},
   758 	{"PbSetColor",					smn_PbSetColor},
   759 	{"PbSetAngle",					smn_PbSetAngle},
   760 	{"PbSetVector",					smn_PbSetVector},
   761 	{"PbSetVector2D",				smn_PbSetVector2D},
   762 	{"PbAddInt",					smn_PbAddInt},
   763 	{"PbAddFloat",					smn_PbAddFloat},
   764 	{"PbAddBool",					smn_PbAddBool},
   765 	{"PbAddString",					smn_PbAddString},
   766 	{"PbAddColor",					smn_PbAddColor},
   767 	{"PbAddAngle",					smn_PbAddAngle},
   768 	{"PbAddVector",					smn_PbAddVector},
   769 	{"PbAddVector2D",				smn_PbAddVector2D},
   770 	{"PbReadMessage",				smn_PbReadMessage},
   771 	{"PbReadRepeatedMessage",		smn_PbReadRepeatedMessage},
   772 	{"PbAddMessage",				smn_PbAddMessage},
   773 	{NULL,							NULL}
   774 };
   775 
   776 /*
   777                                        @@@@@@@@@@@@@ 
   778                                      @@@@@@@@@@@@@@@@@@
   779                                      @@@@@@@@@@@@@@@@@@@@@      
   780                                     @@@@@@@@@@@@@@@@@@@@@@@@               
   781                                    @@@@@@@@    @@@@@@@@@@@@@
   782                                    @@@@@@@@    @@@@@@@@@@@@@          
   783                                       @@@@@@  @@@@@@@@@@@@@@@             
   784                                  0000   @@@@@@@@@@@@@@@@@@@@@                
   785                               000000000   @@@@@@@@@@@@@@@@@@@           
   786                        0000000000000000000   @@@@@@@@@@@@@@@          
   787                        00000000000000000000  @@@@@@@@@@@@@@@            
   788                             000000000       @@@@@@@@@@@@@@@           
   789                                          @@@@@@@@@@@@@@@@@               
   790                                         @@@@@@@@@@@@@@@@@@      
   791                                        @@@@@@@@@@@@@@@@@@       
   792                                        @@@@@@@@@@@@@@@@@@                                                                @@@@
   793                                       @@@@@@@@@@@@@@@@@@@                                                             @@@@@@@  
   794                                      @@@   @@@@    @@@                                                             @@@@@@@@@@     
   795                                     @@@@@@@@@@@@@@@@@@@@@@@@@@                                                 @@@@@@@@@@  @@@@@    
   796                                    @@@@@@@@@@@@@@@@@@@@@@@@@@ @@@   @@@@@@@@                                @@  @@@@@@@@@@@@@@@ 
   797                                   @@@@@@@@@@@@@@@@@@@@@@@@@@ @@   @@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@@@@@  @@  @@@@@@@@@        
   798                                   @@@@@@@@@@@@@@@@@@@@@@@ @@@@   @@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@  @@  @@@@@@@@@@@@@
   799                                   @@@@@@@@@@@@@@@@@@@@@ @@@@    @@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@@@@@@@@  @@@  @@@@@@@@@@@@     
   800                                  @@@@@@@@@@@@@@@@@@@@ @@@@@@   @@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@   @@@@  @@@@@@@@@@@     
   801                                  @@@@@@@@@@@@@@@@@  @@@@@@    @@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@      @@@@@ @@@@@@      
   802                                  @@@@@@@@@       @@@@@@@@@   @@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@     @@  @@@@@ @@@@@@@@   
   803                                            @@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@   @@@@@@  @@@@  @@@@@@  
   804                                   @@@@@@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@@@@@@@  @@@@@@         @@@@@@  @@@@@@
   805                                  @@@@@@@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@@@@@@@              @@@@@@@@   @@@@
   806                                   @@@@@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@       @@@@@@@@@@@@@@  @  @@@@@  
   807                                    @@@@@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@    @@@@@  @@@@    ////
   808                      ////////////   @@@@@@@@@@@ @@@@@@       @@@@@@@@@@@@@@@@@@@@  @@      @@@@@@@@@  @@@@    //// //////////// 
   809               ///////////////// ///    @@@@@          @@@@    @@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@     @@@@   ///// ///////  /////////    
   810         /////////////////////  /////         @@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@   @@@@@@@      @  @@@@    ////// ///////  ///////////////
   811     ///////////////////////// ///////    @@@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@           @@@@@   @@@@    //////  ////////  //////////////////// 
   812  ////////////////////////////  //////////   @@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@   @@@@@@@@@     @@@      //////  ////////// ////////////////////////
   813 //////////////////// //////////  ///////////   @@@@@@@@@@@@@@@@@     @@@@@@@@   @@@      @@@@@@      ////// ////////////  //////////////////////////
   814 //////////////////// ////////////   ///////////   @@@@@@@@@@@@@@@@               @@@@            /////////////////////  /////////////////////////////
   815 /////////////////////  //////////////       //////              @@@@@@@@@                ///////////////////////////////////////////////////////////
   816    ////////////////////    /////////////////////////////////////          ///////////////////////////////////////////////////////////////////////
   817        /////////////////////     ////////////////////////////////////////////////////////////////////////////////////////////////////////////  
   818             ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   819                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////   
   820                              ///////////////////////////////////////////////////////////////////////////////////////// 
   821                                              //////////////////////////////////////////////////////////
   822 */
   823 #endif // USE_PROTOBUF_USERMESSAGES