core/smn_adt_array.cpp
author Phong Dang <teame06@gmail.com>
Wed Aug 01 07:29:40 2007 +0000 (2007-08-01)
changeset 1241 2e8046793bc9
parent 1231 17badaf66ce4
child 1330 ab94316bb52b
permissions -rw-r--r--
Added check to make sure player are alive to perform sm_slap, sm_burn, sm_slay.
     1 /**
     2  * vim: set ts=4 :
     3  * ================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
     6  * ================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or 
     9  * modify it under the terms of the GNU General Public License, 
    10  * version 3.0, as published by the Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16  *
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to 
    21  * link the code of this program (as well as its derivative works) to 
    22  * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
    23  * Game MODs that run on software by the Valve Corporation.  You must 
    24  * obey the GNU General Public License in all respects for all other 
    25  * code used. Additionally, AlliedModders LLC grants this exception 
    26  * to all derivative works. AlliedModders LLC defines further 
    27  * exceptions, found in LICENSE.txt (as of this writing, version 
    28  * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
    29  *
    30  * Version: $Id$
    31  */
    32 
    33 #include <malloc.h>
    34 #include "sm_globals.h"
    35 #include "sm_stringutil.h"
    36 #include "CellArray.h"
    37 #include "HandleSys.h"
    38 
    39 HandleType_t htCellArray;
    40 
    41 class CellArrayHelpers : 
    42 	public SMGlobalClass,
    43 	public IHandleTypeDispatch
    44 {
    45 public: //SMGlobalClass
    46 	void OnSourceModAllInitialized()
    47 	{
    48 		htCellArray = g_HandleSys.CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    49 	}
    50 	void OnSourceModShutdown()
    51 	{
    52 		g_HandleSys.RemoveType(htCellArray, g_pCoreIdent);
    53 	}
    54 public: //IHandleTypeDispatch
    55 	void OnHandleDestroy(HandleType_t type, void *object)
    56 	{
    57 		CellArray *array = (CellArray *)object;
    58 		delete array;
    59 	}
    60 } s_CellArrayHelpers;
    61 
    62 static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)
    63 {
    64 	if (!params[1])
    65 	{
    66 		return pContext->ThrowNativeError("Invalid block size (must be > 0)");
    67 	}
    68 
    69 	CellArray *array = new CellArray(params[1]);
    70 
    71 	if (params[2])
    72 	{
    73 		array->resize(params[2]);
    74 	}
    75 	
    76 	Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
    77 	if (!hndl)
    78 	{
    79 		delete array;
    80 	}
    81 
    82 	return hndl;
    83 }
    84 
    85 static cell_t ClearArray(IPluginContext *pContext, const cell_t *params)
    86 {
    87 	CellArray *array;
    88 	HandleError err;
    89 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
    90 
    91 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
    92 		!= HandleError_None)
    93 	{
    94 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
    95 	}
    96 
    97 	array->clear();
    98 	
    99 	return 1;
   100 }
   101 
   102 static cell_t ResizeArray(IPluginContext *pContext, const cell_t *params)
   103 {
   104 	CellArray *array;
   105 	HandleError err;
   106 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   107 
   108 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   109 		!= HandleError_None)
   110 	{
   111 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   112 	}
   113 
   114 	if (!array->resize(params[2]))
   115 	{
   116 		return pContext->ThrowNativeError("Unable to resize array to \"%u\"", params[2]);
   117 	}
   118 
   119 	return 1;
   120 }
   121 
   122 static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params)
   123 {
   124 	CellArray *array;
   125 	HandleError err;
   126 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   127 
   128 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   129 		!= HandleError_None)
   130 	{
   131 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   132 	}
   133 
   134 	return (cell_t)array->size();
   135 }
   136 
   137 static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params)
   138 {
   139 	CellArray *array;
   140 	HandleError err;
   141 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   142 
   143 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   144 		!= HandleError_None)
   145 	{
   146 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   147 	}
   148 
   149 	cell_t *blk = array->push();
   150 	if (!blk)
   151 	{
   152 		return pContext->ThrowNativeError("Failed to grow array");
   153 	}
   154 
   155 	*blk = params[2];
   156 
   157 	return (cell_t)(array->size() - 1);
   158 }
   159 
   160 static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params)
   161 {
   162 	CellArray *array;
   163 	HandleError err;
   164 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   165 
   166 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   167 		!= HandleError_None)
   168 	{
   169 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   170 	}
   171 
   172 	cell_t *blk = array->push();
   173 	if (!blk)
   174 	{
   175 		return pContext->ThrowNativeError("Failed to grow array");
   176 	}
   177 
   178 	char *str;
   179 	pContext->LocalToString(params[2], &str);
   180 
   181 	strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
   182 
   183 	return (cell_t)(array->size() - 1);
   184 }
   185 
   186 static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params)
   187 {
   188 	CellArray *array;
   189 	HandleError err;
   190 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   191 
   192 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   193 		!= HandleError_None)
   194 	{
   195 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   196 	}
   197 
   198 	cell_t *blk = array->push();
   199 	if (!blk)
   200 	{
   201 		return pContext->ThrowNativeError("Failed to grow array");
   202 	}
   203 
   204 	cell_t *addr;
   205 	pContext->LocalToPhysAddr(params[2], &addr);
   206 
   207 	size_t indexes = array->blocksize();
   208 	if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
   209 	{
   210 		indexes = params[3];
   211 	}
   212 
   213 	memcpy(blk, addr, sizeof(cell_t) * indexes);
   214 
   215 	return (cell_t)(array->size() - 1);
   216 }
   217 
   218 static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params)
   219 {
   220 	CellArray *array;
   221 	HandleError err;
   222 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   223 
   224 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   225 		!= HandleError_None)
   226 	{
   227 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   228 	}
   229 
   230 	size_t idx = (size_t)params[2];
   231 	if (idx >= array->size())
   232 	{
   233 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   234 	}
   235 
   236 	cell_t *blk = array->at(idx);
   237 
   238 	idx = (size_t)params[3];
   239 	if (params[4] == 0)
   240 	{
   241 		if (idx >= array->blocksize())
   242 		{
   243 			return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
   244 		}
   245 		return blk[idx];
   246 	} else {
   247 		if (idx >= array->blocksize() * 4)
   248 		{
   249 			return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
   250 		}
   251 		return (cell_t)*((char *)blk + idx);
   252 	}
   253 
   254 	return 0;
   255 }
   256 
   257 static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params)
   258 {
   259 	CellArray *array;
   260 	HandleError err;
   261 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   262 
   263 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   264 		!= HandleError_None)
   265 	{
   266 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   267 	}
   268 
   269 	size_t idx = (size_t)params[2];
   270 	if (idx >= array->size())
   271 	{
   272 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   273 	}
   274 
   275 	cell_t *blk = array->at(idx);
   276 	size_t numWritten = 0;
   277 
   278 	pContext->StringToLocalUTF8(params[3], params[4], (char *)blk, &numWritten);
   279 
   280 	return numWritten;
   281 }
   282 
   283 static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params)
   284 {
   285 	CellArray *array;
   286 	HandleError err;
   287 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   288 
   289 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   290 		!= HandleError_None)
   291 	{
   292 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   293 	}
   294 
   295 	size_t idx = (size_t)params[2];
   296 	if (idx >= array->size())
   297 	{
   298 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   299 	}
   300 
   301 	cell_t *blk = array->at(idx);
   302 	size_t indexes = array->blocksize();
   303 	if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
   304 	{
   305 		indexes = params[4];
   306 	}
   307 
   308 	cell_t *addr;
   309 	pContext->LocalToPhysAddr(params[3], &addr);
   310 
   311 	memcpy(addr, blk, sizeof(cell_t) * indexes);
   312 
   313 	return indexes;
   314 }
   315 
   316 static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params)
   317 {
   318 	CellArray *array;
   319 	HandleError err;
   320 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   321 
   322 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   323 		!= HandleError_None)
   324 	{
   325 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   326 	}
   327 
   328 	size_t idx = (size_t)params[2];
   329 	if (idx >= array->size())
   330 	{
   331 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   332 	}
   333 
   334 	cell_t *blk = array->at(idx);
   335 
   336 	idx = (size_t)params[4];
   337 	if (params[5] == 0)
   338 	{
   339 		if (idx >= array->blocksize())
   340 		{
   341 			return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
   342 		}
   343 		blk[idx] = params[3];
   344 	} else {
   345 		if (idx >= array->blocksize() * 4)
   346 		{
   347 			return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
   348 		}
   349 		*((char *)blk + idx) = (char)params[3];
   350 	}
   351 
   352 	return 1;
   353 }
   354 
   355 static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
   356 {
   357 	CellArray *array;
   358 	HandleError err;
   359 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   360 
   361 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   362 		!= HandleError_None)
   363 	{
   364 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   365 	}
   366 
   367 	size_t idx = (size_t)params[2];
   368 	if (idx >= array->size())
   369 	{
   370 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   371 	}
   372 
   373 	cell_t *blk = array->at(idx);
   374 
   375 	char *str;
   376 	pContext->LocalToString(params[3], &str);
   377 
   378 	return strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
   379 }
   380 
   381 static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
   382 {
   383 	CellArray *array;
   384 	HandleError err;
   385 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   386 
   387 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   388 		!= HandleError_None)
   389 	{
   390 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   391 	}
   392 
   393 	size_t idx = (size_t)params[2];
   394 	if (idx >= array->size())
   395 	{
   396 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   397 	}
   398 
   399 	cell_t *blk = array->at(idx);
   400 	size_t indexes = array->blocksize();
   401 	if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
   402 	{
   403 		indexes = params[4];
   404 	}
   405 
   406 	cell_t *addr;
   407 	pContext->LocalToPhysAddr(params[3], &addr);
   408 
   409 	memcpy(blk, addr, sizeof(cell_t) * indexes);
   410 
   411 	return indexes;
   412 }
   413 
   414 static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params)
   415 {
   416 	CellArray *array;
   417 	HandleError err;
   418 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   419 
   420 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   421 		!= HandleError_None)
   422 	{
   423 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   424 	}
   425 
   426 	size_t idx = (size_t)params[2];
   427 	if (idx >= array->size())
   428 	{
   429 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   430 	}
   431 
   432 	array->insert_at(idx);
   433 
   434 	return 1;
   435 }
   436 
   437 static cell_t RemoveFromArray(IPluginContext *pContext, const cell_t *params)
   438 {
   439 	CellArray *array;
   440 	HandleError err;
   441 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   442 
   443 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   444 		!= HandleError_None)
   445 	{
   446 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   447 	}
   448 
   449 	size_t idx = (size_t)params[2];
   450 	if (idx >= array->size())
   451 	{
   452 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   453 	}
   454 
   455 	array->remove(idx);
   456 
   457 	return 1;
   458 }
   459 
   460 static cell_t SwapArrayItems(IPluginContext *pContext, const cell_t *params)
   461 {
   462 	CellArray *array;
   463 	HandleError err;
   464 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   465 
   466 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   467 		!= HandleError_None)
   468 	{
   469 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   470 	}
   471 
   472 	size_t idx1 = (size_t)params[2];
   473 	size_t idx2 = (size_t)params[3];
   474 	if (idx1 >= array->size())
   475 	{
   476 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx1, array->size());
   477 	}
   478 	if (idx2 >= array->size())
   479 	{
   480 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx2, array->size());
   481 	}
   482 
   483 	array->swap(idx1, idx2);
   484 
   485 	return 1;
   486 }
   487 
   488 REGISTER_NATIVES(cellArrayNatives)
   489 {
   490 	{"ClearArray",					ClearArray},
   491 	{"CreateArray",					CreateArray},
   492 	{"GetArrayArray",				GetArrayArray},
   493 	{"GetArrayCell",				GetArrayCell},
   494 	{"GetArraySize",				GetArraySize},
   495 	{"GetArrayString",				GetArrayString},
   496 	{"ResizeArray",					ResizeArray},
   497 	{"PushArrayArray",				PushArrayArray},
   498 	{"PushArrayCell",				PushArrayCell},
   499 	{"PushArrayString",				PushArrayString},
   500 	{"RemoveFromArray",				RemoveFromArray},
   501 	{"SetArrayCell",				SetArrayCell},
   502 	{"SetArrayString",				SetArrayString},
   503 	{"SetArrayArray",				SetArrayArray},
   504 	{"ShiftArrayUp",				ShiftArrayUp},
   505 	{"SwapArrayItems",				SwapArrayItems},
   506 	{NULL,							NULL},
   507 };