diff --git a/core/CellArray.h b/core/CellArray.h new file mode 100644 index 00000000..038de834 --- /dev/null +++ b/core/CellArray.h @@ -0,0 +1,149 @@ +/** + * 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 +#include + +class CellArray +{ +public: + CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0) + { + } + ~CellArray() + { + free(m_Data); + } + size_t size() const + { + return m_Size; + } + cell_t *push() + { + if (!GrowIfNeeded(1)) + { + return NULL; + } + cell_t *arr = &m_Data[m_Size * m_BlockSize]; + m_Size++; + return arr; + } + cell_t *at(size_t b) const + { + return &m_Data[b * m_BlockSize]; + } + size_t blocksize() const + { + return m_BlockSize; + } + void clear() + { + m_Size = 0; + } + bool swap(size_t item1, size_t item2) + { + /* Make sure there is extra space available */ + if (!GrowIfNeeded(1)) + { + return false; + } + + cell_t *pri = at(item1); + cell_t *alt = at(item2); + + /* Get our temporary array 1 after the limit */ + cell_t *temp = &m_Data[m_Size * m_BlockSize]; + + memcpy(temp, pri, sizeof(cell_t) * m_BlockSize); + memcpy(pri, alt, sizeof(cell_t) * m_BlockSize); + memcpy(alt, temp, sizeof(cell_t) * m_BlockSize); + + return true; + } + void remove(size_t index) + { + /* If we're at the end, take the easy way out */ + if (index == m_Size - 1) + { + m_Size--; + return; + } + + /* Otherwise, it's time to move stuff! */ + size_t remaining_indexes = (m_Size - 1) - index; + cell_t *src = at(index + 1); + cell_t *dest = at(index); + memmove(dest, src, sizeof(cell_t) * m_BlockSize * remaining_indexes); + + m_Size--; + } + cell_t *insert_at(size_t index) + { + /* Make sure it'll fit */ + if (!GrowIfNeeded(1)) + { + return NULL; + } + + /* move everything up */ + cell_t *src = at(index); + cell_t *dst = at(index + 1); + memmove(dst, src, sizeof(cell_t) * m_BlockSize * m_Size); + + m_Size++; + + return src; + } + bool resize(size_t count) + { + if (count <= m_Size) + { + m_Size = count; + return true; + } + return GrowIfNeeded(m_Size - count); + } +private: + bool GrowIfNeeded(size_t count) + { + /* Shortcut out if we can store this */ + if (m_Size + count <= m_AllocSize) + { + return true; + } + /* Set a base allocation size of 8 items */ + if (!m_AllocSize) + { + m_AllocSize = 8; + } + /* If it's not enough, keep doubling */ + while (m_Size + count > m_AllocSize) + { + m_AllocSize *= 2; + } + /* finally, allocate the new block */ + if (m_Data) + { + m_Data = (cell_t *)realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize); + } else { + m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize); + } + return (m_Data != NULL); + } +private: + cell_t *m_Data; + size_t m_BlockSize; + size_t m_AllocSize; + size_t m_Size; +}; diff --git a/core/Makefile b/core/Makefile index 49a02bc1..11e61b84 100644 --- a/core/Makefile +++ b/core/Makefile @@ -29,7 +29,7 @@ OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \ smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \ smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp smn_handles.cpp smn_keyvalues.cpp \ smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \ - smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp + smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \ systems/LibrarySys.cpp systems/PluginInfoDatabase.cpp systems/PluginSys.cpp \ systems/ShareSys.cpp vm/sp_vm_basecontext.cpp vm/sp_vm_engine.cpp \ diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj index d13cd56c..dc77fd95 100644 --- a/core/msvc8/sourcemod_mm.vcproj +++ b/core/msvc8/sourcemod_mm.vcproj @@ -406,6 +406,10 @@ RelativePath="..\CDataPack.h" > + + @@ -901,6 +905,10 @@ RelativePath="..\smn_admin.cpp" > + + diff --git a/core/smn_adt_array.cpp b/core/smn_adt_array.cpp new file mode 100644 index 00000000..248645b2 --- /dev/null +++ b/core/smn_adt_array.cpp @@ -0,0 +1,489 @@ +/** + * 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 +#include "sm_globals.h" +#include "sm_stringutil.h" +#include "CellArray.h" +#include "HandleSys.h" + +HandleType_t htCellArray; + +class CellArrayHelpers : + public SMGlobalClass, + public IHandleTypeDispatch +{ +public: //SMGlobalClass + void OnSourceModAllInitialized() + { + htCellArray = g_HandleSys.CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL); + } + void OnSourceModShutdown() + { + g_HandleSys.RemoveType(htCellArray, g_pCoreIdent); + } +public: //IHandleTypeDispatch + void OnHandleDestroy(HandleType_t type, void *object) + { + CellArray *array = (CellArray *)object; + delete array; + } +} s_CellArrayHelpers; + +static cell_t CreateArray(IPluginContext *pContext, const cell_t *params) +{ + if (!params[1]) + { + return pContext->ThrowNativeError("Invalid block size (must be > 0)"); + } + + CellArray *array = new CellArray(params[1]); + + if (params[2]) + { + array->resize(params[2]); + } + + Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL); + if (!hndl) + { + delete array; + } + + return hndl; +} + +static cell_t ClearArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + array->clear(); + + return 1; +} + +static cell_t ResizeArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + if (!array->resize(params[2])) + { + return pContext->ThrowNativeError("Unable to resize array to \"%u\"", params[2]); + } + + return 1; +} + +static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + return (cell_t)array->size(); +} + +static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + cell_t *blk = array->push(); + if (!blk) + { + return pContext->ThrowNativeError("Failed to grow array"); + } + + *blk = params[2]; + + return (cell_t)(array->size() - 1); +} + +static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + cell_t *blk = array->push(); + if (!blk) + { + return pContext->ThrowNativeError("Failed to grow array"); + } + + char *str; + pContext->LocalToString(params[2], &str); + + strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t)); + + return (cell_t)(array->size() - 1); +} + +static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + cell_t *blk = array->push(); + if (!blk) + { + return pContext->ThrowNativeError("Failed to grow array"); + } + + cell_t *addr; + pContext->LocalToPhysAddr(params[2], &addr); + + size_t indexes = array->blocksize(); + if (params[3] != -1 && (size_t)params[3] <= array->blocksize()) + { + indexes = params[3]; + } + + memcpy(blk, addr, sizeof(cell_t) * indexes); + + return (cell_t)(array->size() - 1); +} + +static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + + idx = (size_t)params[3]; + if (params[4] == 1) + { + if (idx >= array->blocksize()) + { + return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize()); + } + return blk[idx]; + } else { + if (idx >= array->blocksize() * 4) + { + return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4); + } + return (cell_t)*((char *)blk + idx); + } + + return 0; +} + +static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + size_t numWritten = 0; + + pContext->StringToLocalUTF8(params[3], params[4], (char *)blk, &numWritten); + + return numWritten; +} + +static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + size_t indexes = array->blocksize(); + if (params[4] != -1 && (size_t)params[4] <= array->blocksize()) + { + indexes = params[4]; + } + + cell_t *addr; + pContext->LocalToPhysAddr(params[3], &addr); + + memcpy(addr, blk, sizeof(cell_t) * indexes); + + return indexes; +} + +static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + + idx = (size_t)params[4]; + if (params[5] == 1) + { + if (idx >= array->blocksize()) + { + return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize()); + } + blk[idx] = params[3]; + } else { + if (idx >= array->blocksize() * 4) + { + return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4); + } + *((char *)blk + idx) = (char)params[3]; + } + + return 1; +} + +static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + + char *str; + pContext->LocalToString(params[3], &str); + + return strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t)); +} + +static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + size_t indexes = array->blocksize(); + if (params[4] != -1 && (size_t)params[4] <= array->blocksize()) + { + indexes = params[4]; + } + + cell_t *addr; + pContext->LocalToPhysAddr(params[3], &addr); + + memcpy(blk, addr, sizeof(cell_t) * indexes); + + return indexes; +} + +static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + array->insert_at(idx); + + return 1; +} + +static cell_t RemoveFromArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + array->remove(idx); + + return 1; +} + +static cell_t SwapArrayItems(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx1 = (size_t)params[2]; + size_t idx2 = (size_t)params[3]; + if (idx1 >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx1, array->size()); + } + if (idx2 >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx2, array->size()); + } + + array->swap(idx1, idx2); + + return 1; +} + +REGISTER_NATIVES(cellArrayNatives) +{ + {"ClearArray", ClearArray}, + {"CreateArray", CreateArray}, + {"GetArrayArray", GetArrayArray}, + {"GetArrayCell", GetArrayCell}, + {"GetArraySize", GetArraySize}, + {"GetArrayString", GetArrayString}, + {"ResizeArray", ResizeArray}, + {"PushArrayArray", PushArrayArray}, + {"PushArrayCell", PushArrayCell}, + {"PushArrayString", PushArrayString}, + {"RemoveFromArray", RemoveFromArray}, + {"SetArrayCell", SetArrayCell}, + {"SetArrayString", SetArrayString}, + {"SetArrayArray", SetArrayArray}, + {"ShiftArrayUp", ShiftArrayUp}, + {"SwapArrayItems", SwapArrayItems}, + {NULL, NULL}, +}; diff --git a/plugins/include/adt.inc b/plugins/include/adt.inc new file mode 100644 index 00000000..550a67a0 --- /dev/null +++ b/plugins/include/adt.inc @@ -0,0 +1,21 @@ +/** + * 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 _adt_included + #endinput +#endif +#define _adt_included + +#include diff --git a/plugins/include/adt_array.inc b/plugins/include/adt_array.inc new file mode 100644 index 00000000..06e4b5ff --- /dev/null +++ b/plugins/include/adt_array.inc @@ -0,0 +1,233 @@ +/** + * 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 _adt_array_included + #endinput +#endif +#define _adt_array_included + +/** + * Given a maximum string size (including the null terminator), + * returns the number of cells required to fit that string. + * + * @param size Number of bytes. + * @return Minimum number of cells required to fit the byte count. + */ +stock ByteCountToCells(size) +{ + if (!size) + { + return 1; + } + + return (size + 3) / 4; +} + +/** + * Creates a dynamic global cell array. While slower than a normal array, + * it can be used globally AND dynamically, which is otherwise impossible. + * + * The contents of the array are uniform; i.e. storing a string at index X + * and then retrieving it as an integer is NOT the same as StringToInt()! + * The "blocksize" determines how many cells each array slot has; it cannot + * be changed after creation. + * + * @param blocksize The number of cells each member of the array can + * hold. For example, 32 cells is equivalent to: + * new Array[X][32] + * @param startsize Initial size of the array. Note that data will + * NOT be auto-intialized. + * @return New Handle to the array object. + */ +native Handle:CreateArray(blocksize=1, startsize=0); + +/** + * Clears an array of all entries. This is the same as ResizeArray(0). + * + * @param array Array Handle. + * @noreturn + * @error Invalid Handle. + */ +native ClearArray(Handle:array); + +/** + * Resizes an array. If the size is smaller than the current size, + * the array is truncated. + * + * @param array Array Handle. + * @param newsize New size. + * @noreturn + * @error Invalid Handle or out of memory. + */ +native bool:ResizeArray(Handle:array, newsize); + +/** + * Returns the array size. + * + * @param array Array Handle. + * @return Number of elements in the array. + * @error Invalid Handle. + */ +native GetArraySize(Handle:array); + +/** + * Pushes a value onto the end of an array, adding a new index. + * + * This may safely be used even if the array has a blocksize + * greater than 1. + * + * @param array Array Handle. + * @param value Value to push. + * @return Index of the new entry. + * @error Invalid Handle or out of memory. + */ +native PushArrayCell(Handle:array, any:value); + +/** + * Pushes a string onto the end of an array, truncating it + * if it is too big. + * + * @param array Array Handle. + * @param value String to push. + * @return Index of the new entry. + * @error Invalid Handle or out of memory. + */ +native PushArrayString(Handle:array, const String:value[]); + +/** + * Pushes an array of cells onto the end of an array. The cells + * are pushed as a block (i.e. the entire array sits at the index), + * rather than pushing each cell individually. + * + * @param array Array Handle. + * @param values Block of values to copy. + * @param size If not set, the number of elements copied from the array + * will be equal to the blocksize. If set higher than the + * blocksize, the operation will be truncated. + * @return Index of the new entry. + * @error Invalid Handle or out of memory. + */ +native PushArrayArray(Handle:array, const values[], size=-1); + +/** + * Retrieves a cell value from an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param block Optionally specify which block to read from + * (useful if the blocksize > 0). + * @param asChar Optionally read as a byte instead of a cell. + * @return Value read. + * @error Invalid Handle, invalid index, or invalid block. + */ +native any:GetArrayCell(Handle:array, index, block=0, bool:asChar=false); + +/** + * Retrieves a string value from an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param buffer Buffer to copy to. + * @param maxlength Maximum size of the buffer. + * @return Number of characters copied. + * @error Invalid Handle or invalid index. + */ +native GetArrayString(Handle:array, index, String:buffer[], maxlength); + +/** + * Retrieves an array of cells from an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param buffer Buffer to store the array in. + * @param size If not set, assumes the buffer size is equal to the + * blocksize. Otherwise, the size passed is used. + * @return Number of cells copied. + * @error Invalid Handle or invalid index. + */ +native GetArrayArray(Handle:array, index, buffer[], size=-1); + +/** + * Sets a cell value in an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param value Cell value to set. + * @param block Optionally specify which block to write to + * (useful if the blocksize > 0). + * @param asChar Optionally set as a byte instead of a cell. + * @noreturn + * @error Invalid Handle, invalid index, or invalid block. + */ +native any:SetArrayCell(Handle:array, index, any:value, block=0, bool:asChar=false); + +/** + * Sets a string value in an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param value String value to set. + * @return Number of characters copied. + * @error Invalid Handle or invalid index. + */ +native SetArrayString(Handle:array, index, const String:buffer[]); + +/** + * Sets an array of cells in an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param buffer Array to copy. + * @param size If not set, assumes the buffer size is equal to the + * blocksize. Otherwise, the size passed is used. + * @return Number of cells copied. + * @error Invalid Handle or invalid index. + */ +native SetArrayArray(Handle:array, index, const values[], size=-1); + +/** + * Shifts an array up. All array contents after and including the given + * index are shifted up by one, and the given index is then "free." + * After shifting, the contents of the given index is undefined. + * + * @param array Array Handle. + * @param index Index in the array to shift up from. + * @noreturn + * @error Invalid Handle or invalid index. + */ +native ShiftArrayUp(Handle:array, index); + +/** + * Removes an array index, shifting the entire array down from that position + * on. For example, if item 8 of 10 is removed, the last 3 items will then be + * (6,7,8) instead of (7,8,9), and all indexes before 8 will remain unchanged. + * + * @param array Array Handle. + * @param index Index in the array to remove at. + * @noreturn + * @error Invalid Handle or invalid index. + */ +native RemoveFromArray(Handle:array, index); + +/** + * Swaps two items in the array. + * + * @param array Array Handle. + * @param index1 First index. + * @param index2 Second index. + * @noreturn + * @error Invalid Handle or invalid index. + */ +native SwapArrayItems(Handle:array, index1, index2); diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index 14db8693..d3124444 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -51,6 +51,7 @@ struct Plugin #include #include #include +#include /** * Declare this as a struct in your plugin to expose its information.