Added pseudo dynamic array natives.
Changed some of the "..." tags to "any".
This commit is contained in:
parent
bfe1ff6e15
commit
d563ecb060
|
@ -20,7 +20,7 @@ OBJECTS = meta_api.cpp CFile.cpp CVault.cpp vault.cpp float.cpp file.cpp modules
|
||||||
amxxfile.cpp CLang.cpp md5.cpp emsg.cpp CForward.cpp CPlugin.cpp CModule.cpp \
|
amxxfile.cpp CLang.cpp md5.cpp emsg.cpp CForward.cpp CPlugin.cpp CModule.cpp \
|
||||||
CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \
|
CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \
|
||||||
optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \
|
optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \
|
||||||
amxmod_compat.cpp nongpl_matches.cpp CFlagManager.cpp
|
amxmod_compat.cpp nongpl_matches.cpp CFlagManager.cpp datastructs.cpp
|
||||||
|
|
||||||
LINK = -lgcc -static-libgcc
|
LINK = -lgcc -static-libgcc
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,7 @@ extern AMX_NATIVE_INFO vault_Natives[];
|
||||||
extern AMX_NATIVE_INFO msg_Natives[];
|
extern AMX_NATIVE_INFO msg_Natives[];
|
||||||
extern AMX_NATIVE_INFO vector_Natives[];
|
extern AMX_NATIVE_INFO vector_Natives[];
|
||||||
extern AMX_NATIVE_INFO g_SortNatives[];
|
extern AMX_NATIVE_INFO g_SortNatives[];
|
||||||
|
extern AMX_NATIVE_INFO g_DataStructNatives[];
|
||||||
|
|
||||||
#ifndef __linux__
|
#ifndef __linux__
|
||||||
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
|
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
|
||||||
|
|
607
amxmodx/datastructs.cpp
Normal file
607
amxmodx/datastructs.cpp
Normal file
|
@ -0,0 +1,607 @@
|
||||||
|
/* AMX Mod X
|
||||||
|
*
|
||||||
|
* by the AMX Mod X Development Team
|
||||||
|
* originally developed by OLO
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the author gives permission to
|
||||||
|
* link the code of this program with the Half-Life Game Engine ("HL
|
||||||
|
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||||
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||||
|
* respects for all of the code used other than the HL Engine and MODs
|
||||||
|
* from Valve. If you modify this file, you may extend this exception
|
||||||
|
* to your version of the file, but you are not obligated to do so. If
|
||||||
|
* you do not wish to do so, delete this exception statement from your
|
||||||
|
* version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "amxmodx.h"
|
||||||
|
#include "datastructs.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Note: All handles start at 1. 0 and below are invalid handles.
|
||||||
|
// This way, a plugin that doesn't initialize a vector or
|
||||||
|
// string will not be able to modify another plugin's data
|
||||||
|
// on accident.
|
||||||
|
CVector<CellVector*> VectorHolder;
|
||||||
|
|
||||||
|
|
||||||
|
// Array:ArrayCreate(cellsize=1, reserved=32);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayCreate(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
// params[1] (cellsize) is how big in cells each element is.
|
||||||
|
// this MUST be greater than 0!
|
||||||
|
int cellsize=params[1];
|
||||||
|
|
||||||
|
// params[2] (reserved) is how many elements to allocate
|
||||||
|
// immediately when the list is created.
|
||||||
|
// this MUST be greater than 0!
|
||||||
|
int reserved=params[2];
|
||||||
|
|
||||||
|
if (cellsize<=0)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid array size (%d)", cellsize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (reserved<=0)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid reserved size (%d)", reserved);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan through the vector list to see if any are NULL.
|
||||||
|
// NULL means the vector was previously destroyed.
|
||||||
|
for (unsigned int i=0; i < VectorHolder.size(); ++i)
|
||||||
|
{
|
||||||
|
if (VectorHolder[i]==NULL)
|
||||||
|
{
|
||||||
|
VectorHolder[i]=new CellVector(cellsize);
|
||||||
|
VectorHolder[i]->Grow(reserved);
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// None are NULL, create a new vector
|
||||||
|
CellVector* NewVector=new CellVector(cellsize);
|
||||||
|
NewVector->Grow(reserved);
|
||||||
|
|
||||||
|
VectorHolder.push_back(NewVector);
|
||||||
|
|
||||||
|
return VectorHolder.size();
|
||||||
|
}
|
||||||
|
// ArrayClear(Array:which)
|
||||||
|
static cell AMX_NATIVE_CALL ArrayClear(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->Clear();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArraySize(Array:which)
|
||||||
|
static cell AMX_NATIVE_CALL ArraySize(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec->Size();
|
||||||
|
}
|
||||||
|
// ArrayGetArray(Array:which, item, any:output[]);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayGetArray(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec->GetArray(params[2],get_amxaddr(amx, params[3]))!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid cellvector handle provided (%d:%d:%d)", params[1], params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayGetCell(Array:which, item, any:&output);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayGetCell(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec->GetCell(params[2],get_amxaddr(amx, params[3]))!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid cellvector handle provided (%d:%d:%d)", params[1], params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayGetString(Array:which, item, any:output[], size);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayGetString(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec->GetString(params[2],get_amxaddr(amx, params[3]),params[4])!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid cellvector handle provided (%d:%d:%d)", params[1], params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArraySetArray(Array:which, item, any:output[]);
|
||||||
|
static cell AMX_NATIVE_CALL ArraySetArray(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec->SetArray(params[2],get_amxaddr(amx, params[3]))!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid cellvector handle provided (%d:%d:%d)", params[1], params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArraySetCell(Array:which, item, any:&output);
|
||||||
|
static cell AMX_NATIVE_CALL ArraySetCell(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec->SetCell(params[2], params[3])!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid cellvector handle provided (%d:%d:%d)", params[1], params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArraySetString(Array:which, item, any:output[]);
|
||||||
|
static cell AMX_NATIVE_CALL ArraySetString(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec->SetString(params[2],get_amxaddr(amx, params[3]))!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid cellvector handle provided (%d:%d:%d)", params[1], params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayPushArray(Array:which, any:output[]);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayPushArray(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->SetArray(vec->Push(),get_amxaddr(amx, params[2]));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayPushCell(Array:which, &any:output);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayPushCell(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->SetCell(vec->Push(), params[2]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayPushString(Array:which, any:output[]);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayPushString(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec==NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->SetString(vec->Push(),get_amxaddr(amx, params[2]));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static cell AMX_NATIVE_CALL ArrayGetStringHandle(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell* ptr=vec->GetCellPointer(params[2]);
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<cell>(ptr);
|
||||||
|
|
||||||
|
}
|
||||||
|
// ArrayInsertArrayAfter(Array:which, item, const value[])
|
||||||
|
static cell AMX_NATIVE_CALL ArrayInsertArrayAfter(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int item=params[2]+1;
|
||||||
|
|
||||||
|
if (vec->ShiftUpFrom(item)!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayAfter (%d:%d)", params[1], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->SetArray(item, get_amxaddr(amx, params[3]));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayInsertCellAfter(Array:which, item, value[])
|
||||||
|
static cell AMX_NATIVE_CALL ArrayInsertCellAfter(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int item=params[2]+1;
|
||||||
|
|
||||||
|
if (vec->ShiftUpFrom(item)!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellAfter (%d:%d)", params[1], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->SetCell(item, params[3]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayInsertStringAfter(Array:which, item, const value[])
|
||||||
|
static cell AMX_NATIVE_CALL ArrayInsertStringAfter(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int item=params[2]+1;
|
||||||
|
|
||||||
|
if (vec->ShiftUpFrom(item)!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringAfter (%d:%d)", params[1], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->SetString(item, get_amxaddr(amx, params[3]));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayInsertArrayBefore(Array:which, item, const value[])
|
||||||
|
static cell AMX_NATIVE_CALL ArrayInsertArrayBefore(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int item=params[2];
|
||||||
|
|
||||||
|
if (item==vec->Size())
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayBefore (%d:%d)", params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (vec->ShiftUpFrom(item)!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayBefore (%d:%d)", params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->SetArray(item, get_amxaddr(amx, params[3]));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayInsertCellBefore(Array:which, item, const value)
|
||||||
|
static cell AMX_NATIVE_CALL ArrayInsertCellBefore(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int item=params[2];
|
||||||
|
|
||||||
|
if (item==vec->Size())
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellBefore (%d:%d)", params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (vec->ShiftUpFrom(item)!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellBefore (%d:%d)", params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->SetCell(item, params[3]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// ArrayInsertStringBefore(Array:which, item, const value[])
|
||||||
|
static cell AMX_NATIVE_CALL ArrayInsertStringBefore(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int item=params[2];
|
||||||
|
|
||||||
|
if (item==vec->Size())
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringBefore (%d:%d)", params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (vec->ShiftUpFrom(item)!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringBefore (%d:%d)", params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec->SetString(item, get_amxaddr(amx, params[3]));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArraySwap(Array:which, item1, item2)
|
||||||
|
static cell AMX_NATIVE_CALL ArraySwap(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (vec->Swap(params[2], params[3])!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArraySwap (%d , %d:%d)",params[2], params[3], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArrayDeleteItem(Array:which, item);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayDeleteItem(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec=HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec->Delete(params[2])!=1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayDeleteItem (%d:%d)", params[2], vec->Size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ArrayDestroy(Array:&which)
|
||||||
|
static cell AMX_NATIVE_CALL ArrayDestroy(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
// byref the handle here so we can zero it out after destroying
|
||||||
|
// this way they cannot accidentally reuse it
|
||||||
|
cell* handle=get_amxaddr(amx,params[1]);
|
||||||
|
CellVector* vec=HandleToVector(amx, *handle);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete vec;
|
||||||
|
|
||||||
|
VectorHolder[*handle-1]=NULL;
|
||||||
|
|
||||||
|
*handle=0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct ArraySort_s
|
||||||
|
{
|
||||||
|
int handle;
|
||||||
|
int forward;
|
||||||
|
cell data;
|
||||||
|
cell size;
|
||||||
|
|
||||||
|
} ArraySort_t;
|
||||||
|
|
||||||
|
static CStack<ArraySort_t *> ArraySortStack;
|
||||||
|
|
||||||
|
int SortArrayList(const void *itema, const void *itemb)
|
||||||
|
{
|
||||||
|
ArraySort_t *Info = ArraySortStack.front();
|
||||||
|
|
||||||
|
return executeForwards(Info->forward, Info->handle, *((int *)itema), *((int *)itemb), Info->data, Info->size);
|
||||||
|
|
||||||
|
}
|
||||||
|
// native ArraySort(Array:array, const comparefunc[], data[]="", data_size=0);
|
||||||
|
static cell AMX_NATIVE_CALL ArraySort(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
int handle=params[1];
|
||||||
|
CellVector* vec=HandleToVector(amx, handle);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is kind of a cheating way to go about this but...
|
||||||
|
// Create an array of integers as big as however many elements are in the vector.
|
||||||
|
// Pass that array to qsort
|
||||||
|
// After the array is sorted out, then create a NEW cellvector
|
||||||
|
// and copy in the old data in the order of what was sorted
|
||||||
|
int len;
|
||||||
|
char* FuncName=get_amxstring(amx, params[2], 0, len);
|
||||||
|
// MySortFunc(Array:array, item1, item2, const data[], data_size)
|
||||||
|
int Forward = registerSPForwardByName(amx, FuncName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
|
||||||
|
if (Forward < 0)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", FuncName);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int *IntList=new int[vec->Size()];
|
||||||
|
|
||||||
|
for (int i=0; i< vec->Size(); i++)
|
||||||
|
{
|
||||||
|
IntList[i]=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArraySort_t *Info=new ArraySort_t;
|
||||||
|
|
||||||
|
Info->handle=handle;
|
||||||
|
Info->forward=Forward;
|
||||||
|
Info->data=params[3];
|
||||||
|
Info->size=params[4];
|
||||||
|
|
||||||
|
ArraySortStack.push(Info);
|
||||||
|
qsort(IntList, vec->Size(), sizeof(int), SortArrayList);
|
||||||
|
ArraySortStack.pop();
|
||||||
|
|
||||||
|
CellVector* newvec=new CellVector(vec->GetCellCount());
|
||||||
|
|
||||||
|
// Set the new vector's values
|
||||||
|
for (int i=0; i< vec->Size(); i++)
|
||||||
|
{
|
||||||
|
if (newvec->SetArray(newvec->Push(), vec->GetCellPointer(IntList[i]))!=1)
|
||||||
|
{
|
||||||
|
// This should never happen..
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Failed to SetArray in ArraySort (i=%d, IntList=%d)",i,IntList[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the old vector
|
||||||
|
delete vec;
|
||||||
|
|
||||||
|
// Now save the new vector in its handle location
|
||||||
|
VectorHolder[handle-1]=newvec;
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
delete Info;
|
||||||
|
delete IntList;
|
||||||
|
|
||||||
|
unregisterSPForward(Forward);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AMX_NATIVE_INFO g_DataStructNatives[] =
|
||||||
|
{
|
||||||
|
{ "ArrayCreate", ArrayCreate },
|
||||||
|
{ "ArrayClear", ArrayClear },
|
||||||
|
{ "ArraySize", ArraySize },
|
||||||
|
{ "ArrayGetArray", ArrayGetArray },
|
||||||
|
{ "ArrayGetCell", ArrayGetCell },
|
||||||
|
{ "ArrayGetString", ArrayGetString },
|
||||||
|
{ "ArraySetArray", ArraySetArray },
|
||||||
|
{ "ArraySetCell", ArraySetCell },
|
||||||
|
{ "ArraySetString", ArraySetString },
|
||||||
|
{ "ArrayPushArray", ArrayPushArray },
|
||||||
|
{ "ArrayPushCell", ArrayPushCell },
|
||||||
|
{ "ArrayPushString", ArrayPushString },
|
||||||
|
{ "ArrayInsertArrayAfter", ArrayInsertArrayAfter },
|
||||||
|
{ "ArrayInsertCellAfter", ArrayInsertCellAfter },
|
||||||
|
{ "ArrayInsertStringAfter", ArrayInsertStringAfter },
|
||||||
|
{ "ArrayInsertArrayBefore", ArrayInsertArrayBefore },
|
||||||
|
{ "ArrayInsertCellBefore", ArrayInsertCellBefore },
|
||||||
|
{ "ArrayInsertStringBefore", ArrayInsertStringBefore },
|
||||||
|
{ "ArraySwap", ArraySwap },
|
||||||
|
{ "ArrayDeleteItem", ArrayDeleteItem },
|
||||||
|
{ "ArrayGetStringHandle", ArrayGetStringHandle },
|
||||||
|
{ "ArrayDestroy", ArrayDestroy },
|
||||||
|
{ "ArraySort", ArraySort },
|
||||||
|
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
323
amxmodx/datastructs.h
Normal file
323
amxmodx/datastructs.h
Normal file
|
@ -0,0 +1,323 @@
|
||||||
|
/* AMX Mod X
|
||||||
|
*
|
||||||
|
* by the AMX Mod X Development Team
|
||||||
|
* originally developed by OLO
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the author gives permission to
|
||||||
|
* link the code of this program with the Half-Life Game Engine ("HL
|
||||||
|
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||||
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||||
|
* respects for all of the code used other than the HL Engine and MODs
|
||||||
|
* from Valve. If you modify this file, you may extend this exception
|
||||||
|
* to your version of the file, but you are not obligated to do so. If
|
||||||
|
* you do not wish to do so, delete this exception statement from your
|
||||||
|
* version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DATASTRUCTS_H
|
||||||
|
#define DATASTRUCTS_H
|
||||||
|
|
||||||
|
class CellVector
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
cell* data; // allocated with malloc
|
||||||
|
size_t cellcount; // how many cells per element
|
||||||
|
size_t cursize; // current size of the vector (maximum elements)
|
||||||
|
size_t count; // how many units of the vector are in use
|
||||||
|
|
||||||
|
public:
|
||||||
|
CellVector(): data(NULL), cellcount(0), cursize(0), count(0)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
CellVector(int cellsize): data(NULL), cellcount(cellsize), cursize(0), count(0)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
~CellVector()
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
size_t GetCellCount()
|
||||||
|
{
|
||||||
|
return cellcount;
|
||||||
|
};
|
||||||
|
void Grow(size_t howmany)
|
||||||
|
{
|
||||||
|
cursize+=howmany;
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
data=(cell*)realloc(data, (sizeof(cell) * cellcount) * cursize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data=(cell*)malloc((sizeof(cell) * cellcount) * cursize);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void FreeUnused(void)
|
||||||
|
{
|
||||||
|
if (cursize != count &&
|
||||||
|
data != NULL)
|
||||||
|
{
|
||||||
|
cursize=count;
|
||||||
|
data=(cell*)realloc(data, cursize * (sizeof(cell) * cellcount));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Returns 1 on success
|
||||||
|
// 0 on out of bounds.
|
||||||
|
int GetArray(size_t which, cell* output)
|
||||||
|
{
|
||||||
|
// make sure it is in bounds.
|
||||||
|
if (which >= count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// align output data
|
||||||
|
cell* out=data + (cellcount * which);
|
||||||
|
|
||||||
|
memcpy(output, out, sizeof(cell) * cellcount);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
// Returns 1 on success
|
||||||
|
// 0 on out of bounds
|
||||||
|
int GetCell(size_t which, cell* output)
|
||||||
|
{
|
||||||
|
// check bounds
|
||||||
|
if (which >= count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*output=*(data + (cellcount * which));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Returns 1 on success
|
||||||
|
// 0 on out of bounds
|
||||||
|
int GetString(size_t which, cell* output, size_t size)
|
||||||
|
{
|
||||||
|
// check bounds
|
||||||
|
if (which >= count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cell* out=data + (cellcount * which);
|
||||||
|
|
||||||
|
size_t count=cellcount;
|
||||||
|
|
||||||
|
while (size-- &&
|
||||||
|
count-- &&
|
||||||
|
(*output++=*out++)!='\0')
|
||||||
|
/* do nothing */ ;
|
||||||
|
|
||||||
|
// If size is zero here, then the string was never null terminated.
|
||||||
|
if (size==0)
|
||||||
|
{
|
||||||
|
*out='\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Returns 1 on success
|
||||||
|
// 0 on out of bounds
|
||||||
|
int SetArray(size_t which, cell* output)
|
||||||
|
{
|
||||||
|
if (which >= count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// align output
|
||||||
|
cell* out=data + (cellcount * which);
|
||||||
|
|
||||||
|
memcpy(out, output, sizeof(cell) * cellcount);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
// Returns 1 on success
|
||||||
|
// 0 on out of bounds
|
||||||
|
int SetCell(size_t which, cell output)
|
||||||
|
{
|
||||||
|
if (which >= count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// align output
|
||||||
|
*(data + (cellcount * which))=output;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
// Returns 1 on success
|
||||||
|
// 0 on out of bounds
|
||||||
|
int SetString(size_t which, cell* output)
|
||||||
|
{
|
||||||
|
if (which >= count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// align output
|
||||||
|
cell* out=data + (cellcount * which);
|
||||||
|
|
||||||
|
memcpy(out, output, sizeof(cell) * cellcount);
|
||||||
|
|
||||||
|
// now force a null terminator on the last entry.
|
||||||
|
out+=(cellcount - 1);
|
||||||
|
*out='\0';
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
int Push()
|
||||||
|
{
|
||||||
|
if (count >= cursize)
|
||||||
|
{
|
||||||
|
// Grow in 8s to cause less reallocation
|
||||||
|
this->Grow(8);
|
||||||
|
};
|
||||||
|
|
||||||
|
this->count++;
|
||||||
|
|
||||||
|
return this->count-1;
|
||||||
|
};
|
||||||
|
int Size()
|
||||||
|
{
|
||||||
|
return this->count;
|
||||||
|
};
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
data=(cell*)malloc(sizeof(cell) * cellcount);
|
||||||
|
cursize=1;
|
||||||
|
count=0;
|
||||||
|
};
|
||||||
|
cell* GetCellPointer(size_t which)
|
||||||
|
{
|
||||||
|
if (which >= count)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return data + (which * cellcount);
|
||||||
|
};
|
||||||
|
// Shifts all items from this item, and including this item up 1.
|
||||||
|
int ShiftUpFrom(size_t which)
|
||||||
|
{
|
||||||
|
// No point shifting this.
|
||||||
|
if (this->count < 0 ||
|
||||||
|
which > this->count)
|
||||||
|
{
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// First make a new item.
|
||||||
|
this->Push();
|
||||||
|
|
||||||
|
// If we got an InsertAfter(lastitem), then which will equal this->count - 1
|
||||||
|
// all we needed to do was Push()
|
||||||
|
if (which == this->count ||
|
||||||
|
which == this->count - 1)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a temporary buffer to store data in
|
||||||
|
size_t tempbuffsize=(sizeof(cell) * cellcount) * (this->count - which);
|
||||||
|
|
||||||
|
cell* temp=(cell*)malloc(tempbuffsize);
|
||||||
|
|
||||||
|
// Copy old data to temp buffer
|
||||||
|
memcpy(temp, GetCellPointer(which), tempbuffsize);
|
||||||
|
|
||||||
|
// Now copy temp buffer to adjusted location
|
||||||
|
memcpy(GetCellPointer(which+1), temp, tempbuffsize);
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
free(temp);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
};
|
||||||
|
// Shifts all items from this item, and including this item down 1.
|
||||||
|
// This deletes the item specified.
|
||||||
|
int Delete(size_t which)
|
||||||
|
{
|
||||||
|
// No point shifting this.
|
||||||
|
if (this->count < 0 ||
|
||||||
|
which >= this->count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (size_t i=which; i<this->count - 1; i++)
|
||||||
|
{
|
||||||
|
memcpy(GetCellPointer(i), GetCellPointer(i + 1), sizeof(cell) * cellcount);
|
||||||
|
}
|
||||||
|
this->count--;
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
int Swap(size_t item1, size_t item2)
|
||||||
|
{
|
||||||
|
if (item1 >= this->count ||
|
||||||
|
item2 >= this->count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a temp buffer to store item2
|
||||||
|
cell* temp=(cell*)malloc(sizeof(cell) * cellcount);
|
||||||
|
memcpy(temp, GetCellPointer(item2), sizeof(cell) * cellcount);
|
||||||
|
|
||||||
|
// copy item1 to item2
|
||||||
|
memcpy(GetCellPointer(item2), GetCellPointer(item1), sizeof(cell) * cellcount);
|
||||||
|
|
||||||
|
// copy item2 to item1
|
||||||
|
memcpy(GetCellPointer(item1), temp, sizeof(cell) * cellcount);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
free(temp);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CVector<CellVector*> VectorHolder;
|
||||||
|
|
||||||
|
|
||||||
|
inline CellVector* HandleToVector(AMX* amx, int handle)
|
||||||
|
{
|
||||||
|
if (handle <= 0 ||
|
||||||
|
handle > (int)VectorHolder.size())
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CellVector* ret=VectorHolder[handle-1];
|
||||||
|
|
||||||
|
if (ret == NULL)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,6 @@
|
||||||
#include "amxmodx.h"
|
#include "amxmodx.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
#include "datastructs.h"
|
||||||
#include "amxmod_compat.h"
|
#include "amxmod_compat.h"
|
||||||
|
|
||||||
//Adapted from Quake3's vsprintf
|
//Adapted from Quake3's vsprintf
|
||||||
|
@ -494,6 +495,21 @@ reswitch:
|
||||||
AddHex(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
|
AddHex(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
|
||||||
arg++;
|
arg++;
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
{
|
||||||
|
CHECK_ARGS(0);
|
||||||
|
// %S is passed a pointer directly to a cell string.
|
||||||
|
cell* ptr=reinterpret_cast<cell*>(*get_amxaddr(amx, params[arg]));
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid vector string handle provided (%d)", *get_amxaddr(amx, params[arg]));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddString(&buf_p, llen, ptr, width, prec);
|
||||||
|
arg++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 's':
|
case 's':
|
||||||
CHECK_ARGS(0);
|
CHECK_ARGS(0);
|
||||||
if (amx->flags & AMX_FLAG_OLDFILE)
|
if (amx->flags & AMX_FLAG_OLDFILE)
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "amxmod_compat.h"
|
#include "amxmod_compat.h"
|
||||||
|
|
||||||
|
#include "datastructs.h"
|
||||||
#include "CFlagManager.h"
|
#include "CFlagManager.h"
|
||||||
#include "svn_version.h"
|
#include "svn_version.h"
|
||||||
|
|
||||||
|
@ -388,6 +389,12 @@ int C_Spawn(edict_t *pent)
|
||||||
|
|
||||||
FlagMan.LoadFile();
|
FlagMan.LoadFile();
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<VectorHolder.size(); i++)
|
||||||
|
{
|
||||||
|
delete VectorHolder[i];
|
||||||
|
};
|
||||||
|
VectorHolder.clear();
|
||||||
|
|
||||||
char map_pluginsfile_path[256];
|
char map_pluginsfile_path[256];
|
||||||
char configs_dir[256];
|
char configs_dir[256];
|
||||||
|
|
||||||
|
|
|
@ -578,6 +578,7 @@ int set_amxnatives(AMX* amx, char error[128])
|
||||||
amx_Register(amx, msg_Natives, -1);
|
amx_Register(amx, msg_Natives, -1);
|
||||||
amx_Register(amx, vector_Natives, -1);
|
amx_Register(amx, vector_Natives, -1);
|
||||||
amx_Register(amx, g_SortNatives, -1);
|
amx_Register(amx, g_SortNatives, -1);
|
||||||
|
amx_Register(amx, g_DataStructNatives, -1);
|
||||||
|
|
||||||
if (amx->flags & AMX_FLAG_OLDFILE)
|
if (amx->flags & AMX_FLAG_OLDFILE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -770,6 +770,14 @@
|
||||||
RelativePath="..\CVector.h"
|
RelativePath="..\CVector.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\datastructs.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\datastructs.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\debugger.h"
|
RelativePath="..\debugger.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -41,6 +41,8 @@
|
||||||
#include <sqlx>
|
#include <sqlx>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
new Vector:AdminList;
|
||||||
|
|
||||||
new AdminCount;
|
new AdminCount;
|
||||||
|
|
||||||
new PLUGINNAME[] = "AMX Mod X"
|
new PLUGINNAME[] = "AMX Mod X"
|
||||||
|
@ -108,6 +110,11 @@ public plugin_init()
|
||||||
|
|
||||||
server_cmd("exec %s/amxx.cfg", configsDir) // Execute main configuration file
|
server_cmd("exec %s/amxx.cfg", configsDir) // Execute main configuration file
|
||||||
server_cmd("exec %s/sql.cfg", configsDir)
|
server_cmd("exec %s/sql.cfg", configsDir)
|
||||||
|
|
||||||
|
// Create a vector of 5 cells to store the info.
|
||||||
|
AdminList=vector_create(5);
|
||||||
|
|
||||||
|
|
||||||
#if defined USING_SQL
|
#if defined USING_SQL
|
||||||
server_cmd("amx_sqladmins")
|
server_cmd("amx_sqladmins")
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <messages>
|
#include <messages>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sorting>
|
#include <sorting>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
/* Function is called just after server activation.
|
/* Function is called just after server activation.
|
||||||
* Good place for configuration loading, commands and cvars registration. */
|
* Good place for configuration loading, commands and cvars registration. */
|
||||||
|
@ -97,16 +98,16 @@ native get_localinfo(const info[],output[],len);
|
||||||
native show_motd(player,const message[],const header[]="");
|
native show_motd(player,const message[],const header[]="");
|
||||||
|
|
||||||
/* Sends message to player. Set index to 0 to send text globaly. */
|
/* Sends message to player. Set index to 0 to send text globaly. */
|
||||||
native client_print(index,type,const message[],{Float,Sql,Result,_}:...);
|
native client_print(index,type,const message[],any:...);
|
||||||
|
|
||||||
/* Sends message to player by engine. Set index to 0 to send text globaly. */
|
/* Sends message to player by engine. Set index to 0 to send text globaly. */
|
||||||
native engclient_print(player,type,const message[],{Float,Sql,Result,_}:...);
|
native engclient_print(player,type,const message[],any:...);
|
||||||
|
|
||||||
/* Sends message to console. */
|
/* Sends message to console. */
|
||||||
native console_print(id,const message[],{Float,Sql,Result,_}:...);
|
native console_print(id,const message[],any:...);
|
||||||
|
|
||||||
/* Sends command to console. */
|
/* Sends command to console. */
|
||||||
native console_cmd(id,const cmd[],{Float,Sql,Result,_}:...);
|
native console_cmd(id,const cmd[],any:...);
|
||||||
|
|
||||||
/* Registers event on which a given function will be called
|
/* Registers event on which a given function will be called
|
||||||
* Flags:
|
* Flags:
|
||||||
|
@ -141,7 +142,7 @@ native register_logevent(const function[], argsnum, ... );
|
||||||
native set_hudmessage(red=200, green=100, blue=0, Float:x=-1.0, Float:y=0.35, effects=0, Float:fxtime=6.0, Float:holdtime=12.0, Float:fadeintime=0.1, Float:fadeouttime=0.2,channel=4);
|
native set_hudmessage(red=200, green=100, blue=0, Float:x=-1.0, Float:y=0.35, effects=0, Float:fxtime=6.0, Float:holdtime=12.0, Float:fadeintime=0.1, Float:fadeouttime=0.2,channel=4);
|
||||||
|
|
||||||
/* Displays HUD message to given player. */
|
/* Displays HUD message to given player. */
|
||||||
native show_hudmessage(index,const message[],{Float,Sql,Result,_}:...);
|
native show_hudmessage(index,const message[],any:...);
|
||||||
|
|
||||||
/* Displays menu. Keys have bit values (key 1 is (1<<0), key 5 is (1<<4) etc.). */
|
/* Displays menu. Keys have bit values (key 1 is (1<<0), key 5 is (1<<4) etc.). */
|
||||||
native show_menu(index,keys,const menu[], time = -1, const title[] = "");
|
native show_menu(index,keys,const menu[], time = -1, const title[] = "");
|
||||||
|
@ -150,7 +151,7 @@ native show_menu(index,keys,const menu[], time = -1, const title[] = "");
|
||||||
* When you are asking for string the array and length is needed (read_data(2,name,len)).
|
* When you are asking for string the array and length is needed (read_data(2,name,len)).
|
||||||
* Integer is returned by function (new me = read_data(3)).
|
* Integer is returned by function (new me = read_data(3)).
|
||||||
* Float is set in second parameter (read_data(3,value)). */
|
* Float is set in second parameter (read_data(3,value)). */
|
||||||
native read_data(value, {Float,Sql,Result,_}:... );
|
native read_data(value, any:... );
|
||||||
|
|
||||||
/* Returns number of values in client message. */
|
/* Returns number of values in client message. */
|
||||||
native read_datanum();
|
native read_datanum();
|
||||||
|
@ -171,7 +172,7 @@ native parse_loguser(const text[], name[], nlen, &userid = -2, authid[] = "", al
|
||||||
|
|
||||||
/* Prints message to server console.
|
/* Prints message to server console.
|
||||||
* You may use text formating (f.e. server_print("%-32s %.2f!","hello",7.345)) */
|
* You may use text formating (f.e. server_print("%-32s %.2f!","hello",7.345)) */
|
||||||
native server_print(const message[], {Float,Sql,Result,_}:...);
|
native server_print(const message[], any:...);
|
||||||
|
|
||||||
/* Returns 1 or 0. */
|
/* Returns 1 or 0. */
|
||||||
native is_map_valid(const mapname[]);
|
native is_map_valid(const mapname[]);
|
||||||
|
@ -305,13 +306,13 @@ native user_kill(index,flag=0);
|
||||||
* ... - optional parameters
|
* ... - optional parameters
|
||||||
* Return value:
|
* Return value:
|
||||||
* always 0 */
|
* always 0 */
|
||||||
native log_amx(const string[], {Float,Sql,Result,_}:...);
|
native log_amx(const string[], any:...);
|
||||||
|
|
||||||
/* Sends message to standard HL logs. */
|
/* Sends message to standard HL logs. */
|
||||||
native log_message(const message[],{Float,Sql,Result,_}:...);
|
native log_message(const message[],any:...);
|
||||||
|
|
||||||
/* Sends log message to specified file. */
|
/* Sends log message to specified file. */
|
||||||
native log_to_file(const file[],const message[],{Float,Sql,Result,_}:...);
|
native log_to_file(const file[],const message[],any:...);
|
||||||
|
|
||||||
/* Returns number of players put in server.
|
/* Returns number of players put in server.
|
||||||
* If flag is set then also connecting are counted. */
|
* If flag is set then also connecting are counted. */
|
||||||
|
@ -367,7 +368,7 @@ native find_player(const flags[], ... );
|
||||||
native remove_quotes(text[]);
|
native remove_quotes(text[]);
|
||||||
|
|
||||||
/* Executes command on player. */
|
/* Executes command on player. */
|
||||||
native client_cmd(index,const command[],{Float,Sql,Result,_}:...);
|
native client_cmd(index,const command[],any:...);
|
||||||
|
|
||||||
/* This is an emulation of a client command (commands aren't send to client!).
|
/* This is an emulation of a client command (commands aren't send to client!).
|
||||||
* It allows to execute some commands on players and bots.
|
* It allows to execute some commands on players and bots.
|
||||||
|
@ -376,7 +377,7 @@ native client_cmd(index,const command[],{Float,Sql,Result,_}:...);
|
||||||
native engclient_cmd(index,const command[],const arg1[]="",const arg2[]="");
|
native engclient_cmd(index,const command[],const arg1[]="",const arg2[]="");
|
||||||
|
|
||||||
/* Executes command on a server console. */
|
/* Executes command on a server console. */
|
||||||
native server_cmd(const command[],{Float,Sql,Result,_}:...);
|
native server_cmd(const command[],any:...);
|
||||||
|
|
||||||
/* Sets a cvar to given value. */
|
/* Sets a cvar to given value. */
|
||||||
native set_cvar_string(const cvar[],const value[]);
|
native set_cvar_string(const cvar[],const value[]);
|
||||||
|
@ -991,7 +992,7 @@ native CreateHudSyncObj(num=0, ...);
|
||||||
* You must use set_hudmessage, although the channel parameter is
|
* You must use set_hudmessage, although the channel parameter is
|
||||||
* entirely ignored.
|
* entirely ignored.
|
||||||
*/
|
*/
|
||||||
native ShowSyncHudMsg(target, syncObj, const fmt[], {Float,Sql,Result,_}:...);
|
native ShowSyncHudMsg(target, syncObj, const fmt[], any:...);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the display on a HudSync Object. This is essentially the same
|
* Clears the display on a HudSync Object. This is essentially the same
|
||||||
|
|
250
plugins/include/array.inc
Normal file
250
plugins/include/array.inc
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
#if defined _array_included
|
||||||
|
#endinput
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _array_included
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These arrays are intended to be used for a form of global storage without
|
||||||
|
* requiring a #define that needs to be increased each time a person needs more
|
||||||
|
* storage.
|
||||||
|
* These are not designed to be used as a replacement for normal arrays, as
|
||||||
|
* normal arrays are faster and should be used whenever possible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a handle to a dynamically sized array.
|
||||||
|
* It is very important that the cellsize you provide matches up with the buffer sizes
|
||||||
|
* that you pass with subsequent Array{Get,Set,Push} calls.
|
||||||
|
*
|
||||||
|
* @param cellsize How many cells each entry in the array is.
|
||||||
|
* @param reserved How many blank entries are created immediately when the array is created. These entries are not valid to read from until called with ArraySet.
|
||||||
|
* @return Handle to the array.
|
||||||
|
*/
|
||||||
|
native Array:ArrayCreate(cellsize=1, reserved=32);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all entries from the array.
|
||||||
|
*
|
||||||
|
* @param which The array to clear.
|
||||||
|
* @return 1 on success, 0 on failure.
|
||||||
|
*/
|
||||||
|
native ArrayClear(Array:which);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of elements in the array.
|
||||||
|
*
|
||||||
|
* @param which The array to check.
|
||||||
|
* @return How many elements are in the array.
|
||||||
|
*/
|
||||||
|
native ArraySize(Array:which);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns data within an array.
|
||||||
|
* Make sure the output buffer matches the size the array was created with!
|
||||||
|
*
|
||||||
|
* @param which The array to retrieve the item from.
|
||||||
|
* @param item The item to retrieve (zero-based).
|
||||||
|
* @param output The output buffer to write.
|
||||||
|
*/
|
||||||
|
native ArrayGetArray(Array:which, item, any:output[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a single cell of data from an array.
|
||||||
|
* Use this only with arrays that were created with a cellsize of 1!
|
||||||
|
*
|
||||||
|
* @param which The array to retrieve the item from.
|
||||||
|
* @param item The item to retrieve (zero-based).
|
||||||
|
* @param output The variable to store the value in.
|
||||||
|
*/
|
||||||
|
native ArrayGetCell(Array:which, item, &any:output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string value from an array.
|
||||||
|
*
|
||||||
|
* @param which The array to retrieve the item from.
|
||||||
|
* @param item The item to retrieve (zero-based).
|
||||||
|
* @param output The variable to store the value in.
|
||||||
|
* @param size Character size of the output buffer.
|
||||||
|
*/
|
||||||
|
native ArrayGetString(Array:which, item, output[], size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an item's data with that of a local buffer.
|
||||||
|
* The buffer size must match what the cellsize that the array was created with!
|
||||||
|
* The item must already exist, use ArrayPushArray to create a new item within the array.
|
||||||
|
*
|
||||||
|
* @param which The array to set the item from within.
|
||||||
|
* @param item The item to set (zero-based).
|
||||||
|
* @param input The input buffer to store.
|
||||||
|
*/
|
||||||
|
native ArraySetArray(Array:which, item, const any:input[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an array's single cell value. Use this only on array that were created with a cellsize of 1!
|
||||||
|
* The item must already exist, use ArrayPushCell to create a new item within the array.
|
||||||
|
*
|
||||||
|
* @param which The array to set the item from within.
|
||||||
|
* @param item The item to set (zero-based).
|
||||||
|
* @param input The value to set.
|
||||||
|
*/
|
||||||
|
native ArraySetCell(Array:which, item, any:input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a string value from an array.
|
||||||
|
* The stored string will be truncated if it is longer than the cellsize the array was created with!
|
||||||
|
* The item must already exist, use ArrayPushString to create a new item within the array.
|
||||||
|
*
|
||||||
|
* @param which The array to set the item from within.
|
||||||
|
* @param item The item to set (zero-based).
|
||||||
|
* @param input The string to set the item as.
|
||||||
|
*/
|
||||||
|
native ArraySetString(Array:which, item, const input[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new item at the end of the array and sets its data with that of a local buffer.
|
||||||
|
* The buffer size must match what the cellsize that the array was created with!
|
||||||
|
*
|
||||||
|
* @param which The array to add the item to.
|
||||||
|
* @param input The input buffer to store.
|
||||||
|
*/
|
||||||
|
native ArrayPushArray(Array:which, const any:input[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new item and sets the array's single cell value.
|
||||||
|
* Use this only on array that were created with a cellsize of 1!
|
||||||
|
*
|
||||||
|
* @param which The array to add the item to.
|
||||||
|
* @param input The value to set.
|
||||||
|
*/
|
||||||
|
native ArrayPushCell(Array:which, any:input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new element in the array and sets its value to the input buffer.
|
||||||
|
* The stored string will be truncated if it is longer than the cellsize the array was created with!
|
||||||
|
*
|
||||||
|
* @param which The array to add the item to.
|
||||||
|
* @param input The string to set the item as.
|
||||||
|
*/
|
||||||
|
native ArrayPushString(Array:which, const input[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an item after the selected item. All items beyond it get shifted up 1 space.
|
||||||
|
* The buffer size must match what the cellsize that the array was created with!
|
||||||
|
*
|
||||||
|
* @param which The array to add the item to.
|
||||||
|
* @param item The item to insert after.
|
||||||
|
* @param input The input buffer to store.
|
||||||
|
*/
|
||||||
|
native ArrayInsertArrayAfter(Array:which, item, const any:input[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an item after the selected item. All items beyond it get shifted up 1 space.
|
||||||
|
* Use this only on an array that was created with a cellsize of 1!
|
||||||
|
*
|
||||||
|
* @param which The array to add the item to.
|
||||||
|
* @param item The item to insert after.
|
||||||
|
* @param input The value to set.
|
||||||
|
*/
|
||||||
|
native ArrayInsertCellAfter(Array:which, item, any:input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an item after the selected item. All items beyond it get shifted up 1 space.
|
||||||
|
* The stored string will be truncated if it is longer than the cellsize the array was created with!
|
||||||
|
*
|
||||||
|
* @param which The array to add the item to.
|
||||||
|
* @param item The item to insert after.
|
||||||
|
* @param input The value to set.
|
||||||
|
*/
|
||||||
|
native ArrayInsertStringAfter(Array:which, item, const input[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an item before the selected item. All items beyond it, and the selected item get shifted up 1 space.
|
||||||
|
* The buffer size must match what the cellsize that the array was created with!
|
||||||
|
*
|
||||||
|
* @param which The array to add the item to.
|
||||||
|
* @param item The item to insert before.
|
||||||
|
* @param input The input buffer to store.
|
||||||
|
*/
|
||||||
|
native ArrayInsertArrayBefore(Array:which, item, const any:input[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an item before the selected item. All items beyond it, and the selected item get shifted up 1 space.
|
||||||
|
* Use this only on an array that was created with a cellsize of 1!
|
||||||
|
*
|
||||||
|
* @param which The array to add the item to.
|
||||||
|
* @param item The item to insert after.
|
||||||
|
* @param input The value to set.
|
||||||
|
*/
|
||||||
|
native ArrayInsertCellBefore(Array:which, item, const any:input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an item before the selected item. All items beyond it, and the selected item get shifted up 1 space.
|
||||||
|
* The stored string will be truncated if it is longer than the cellsize the array was created with!
|
||||||
|
*
|
||||||
|
* @param which The array to add the item to.
|
||||||
|
* @param item The item to insert before.
|
||||||
|
* @param input The value to set.
|
||||||
|
*/
|
||||||
|
native ArrayInsertStringBefore(Array:which, item, const input[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swaps the position of two items.
|
||||||
|
*
|
||||||
|
* @param which The array that contains the items.
|
||||||
|
* @param item1 The first item to swap.
|
||||||
|
* @param item2 The second item to swap.
|
||||||
|
*/
|
||||||
|
native ArraySwap(Array:which, item1, item2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an item from the array. All items beyond it get shifted down 1 space.
|
||||||
|
*
|
||||||
|
* @param which The array that contains the item to delete.
|
||||||
|
* @param item The item to delete.
|
||||||
|
*/
|
||||||
|
native ArrayDeleteItem(Array:which, item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a handle that is passable to a format compliant routine for printing as a string (with the %S parameter).
|
||||||
|
* It is suggested to pass the function directly as a parameter to the format routine.
|
||||||
|
* The array contents must be a null-terminated string!
|
||||||
|
*
|
||||||
|
* An example usage: client_print(id, print_chat, "%S", ArrayGetStringHandle(MessageArray, i));
|
||||||
|
*
|
||||||
|
* @param which The array the string is stored in.
|
||||||
|
* @param item Which item to print the string value of.
|
||||||
|
* @return Handle to the item directly. Do not use or save stale handles.
|
||||||
|
*/
|
||||||
|
native DoNotUse:ArrayGetStringHandle(Array:which, item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the array, and resets the handle to 0 to prevent accidental usage after it is destroyed.
|
||||||
|
*
|
||||||
|
* @param which The array to destroy.
|
||||||
|
*/
|
||||||
|
native ArrayDestroy(&Array:which);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to sorting.inc's CustomSort.
|
||||||
|
* The sorting algorithm then uses your comparison function to sort the data.
|
||||||
|
* The function is called in the following manner:
|
||||||
|
*
|
||||||
|
* public MySortFunc(Array:array, item1, item2, const data[], data_size)
|
||||||
|
*
|
||||||
|
* array - Array handle in its current un-sorted state.
|
||||||
|
* item1, item2 - Current item pair being compared
|
||||||
|
* data[] - Extra data array you passed to the sort func.
|
||||||
|
* data_size - Size of extra data you passed to the sort func.
|
||||||
|
*
|
||||||
|
* Your function should return:
|
||||||
|
* -1 if item1 should go before item2
|
||||||
|
* 0 if item1 and item2 are equal
|
||||||
|
* 1 if item1 should go after item2
|
||||||
|
* Note that the parameters after item2 are all optional and you do not need to specify them.
|
||||||
|
*
|
||||||
|
* Note that unlike the sorting.inc versions, the array passed to the callback is not in mid-sorted state.
|
||||||
|
*/
|
||||||
|
native ArraySort(Array:array, const comparefunc[], data[]="", data_size=0);
|
|
@ -22,7 +22,7 @@
|
||||||
#pragma library engine
|
#pragma library engine
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
native traceresult(type,{Float,Sql,Result,_}:...);
|
native traceresult(type,any:...);
|
||||||
|
|
||||||
/* Registers a client impulse to a function. Function is passed the ID of the user. */
|
/* Registers a client impulse to a function. Function is passed the ID of the user. */
|
||||||
native register_impulse(impulse, const function[]);
|
native register_impulse(impulse, const function[]);
|
||||||
|
@ -39,7 +39,7 @@ native register_think(const Classname[], const function[]);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Precaches an event. */
|
/* Precaches an event. */
|
||||||
native precache_event(type, const Name[], {Float,Sql,Result,_}:...);
|
native precache_event(type, const Name[], any:...);
|
||||||
|
|
||||||
/* set/get a user's speak flags */
|
/* set/get a user's speak flags */
|
||||||
native set_speak(iIndex, iSpeakFlags);
|
native set_speak(iIndex, iSpeakFlags);
|
||||||
|
@ -174,11 +174,11 @@ native playback_event(flags,invoker,eventindex,Float:delay,const Float:origin[3]
|
||||||
/* Gets parameters sent from CmdStart.
|
/* Gets parameters sent from CmdStart.
|
||||||
Note that you will receive modified values if any other plugin have
|
Note that you will receive modified values if any other plugin have
|
||||||
changed them. */
|
changed them. */
|
||||||
native get_usercmd(type,{Float,Sql,Result,_}:...);
|
native get_usercmd(type,any:...);
|
||||||
|
|
||||||
/* Sets the parameters sent from CmdStart.
|
/* Sets the parameters sent from CmdStart.
|
||||||
Note that your changes will be seen by any other plugin doing get_usercmd() */
|
Note that your changes will be seen by any other plugin doing get_usercmd() */
|
||||||
native set_usercmd(type,{Float,Sql,Result,_}:...);
|
native set_usercmd(type,any:...);
|
||||||
|
|
||||||
/* Converts a string offset into a real string. Some of the forwards in fakemeta
|
/* Converts a string offset into a real string. Some of the forwards in fakemeta
|
||||||
uses string offsets. (FM_CreateNamedEntity) */
|
uses string offsets. (FM_CreateNamedEntity) */
|
||||||
|
|
|
@ -31,10 +31,10 @@
|
||||||
* new ptr, classname[32]
|
* new ptr, classname[32]
|
||||||
* pev(entid, pev_classname, ptr, classname, 31)
|
* pev(entid, pev_classname, ptr, classname, 31)
|
||||||
*/
|
*/
|
||||||
native pev(_index,_value,{Float,Sql,Result,_}:...);
|
native pev(_index,_value,any:...);
|
||||||
|
|
||||||
/* Sets entvar data for an entity. Use the pev_* enum */
|
/* Sets entvar data for an entity. Use the pev_* enum */
|
||||||
native set_pev(_index,_value,{Float,Sql,Result,_}:...);
|
native set_pev(_index,_value,any:...);
|
||||||
|
|
||||||
/* returns 0 if ent is invalid, >0 if valid
|
/* returns 0 if ent is invalid, >0 if valid
|
||||||
* (1 == valid, 2 == valid+pvPrivateData valid)
|
* (1 == valid, 2 == valid+pvPrivateData valid)
|
||||||
|
@ -50,7 +50,7 @@ native pev_valid(entindex);
|
||||||
* new ptr = pev(id, pev_viewmodel)
|
* new ptr = pev(id, pev_viewmodel)
|
||||||
* global_get(glb_pStringBase, ptr, model, 127)
|
* global_get(glb_pStringBase, ptr, model, 127)
|
||||||
*/
|
*/
|
||||||
native global_get(_value, {Float,Sql,Result,_}:...);
|
native global_get(_value, any:...);
|
||||||
|
|
||||||
/* Returns an integer from private data. _linuxdiff is added into the _Offset if it's used on a linux server. */
|
/* Returns an integer from private data. _linuxdiff is added into the _Offset if it's used on a linux server. */
|
||||||
native get_pdata_int(_index,_Offset,_linuxdiff=5);
|
native get_pdata_int(_index,_Offset,_linuxdiff=5);
|
||||||
|
@ -77,7 +77,7 @@ native register_forward(_forwardType,const _function[],_post=0);
|
||||||
native unregister_forward(_forwardType, registerId, post=0);
|
native unregister_forward(_forwardType, registerId, post=0);
|
||||||
|
|
||||||
/* Returns data for metamod */
|
/* Returns data for metamod */
|
||||||
native forward_return(type,{Float,Sql,Result,_}:...);
|
native forward_return(type,any:...);
|
||||||
|
|
||||||
/* Returns the original return value of an engine function.
|
/* Returns the original return value of an engine function.
|
||||||
* This is only valid in forwards that were registered as post.
|
* This is only valid in forwards that were registered as post.
|
||||||
|
@ -89,7 +89,7 @@ native forward_return(type,{Float,Sql,Result,_}:...);
|
||||||
native get_orig_retval({Float,_}:...);
|
native get_orig_retval({Float,_}:...);
|
||||||
|
|
||||||
native engfunc(type,{Float,Sql,Result,AlertType,_}:...);
|
native engfunc(type,{Float,Sql,Result,AlertType,_}:...);
|
||||||
native dllfunc(type,{Float,Sql,Result,_}:...);
|
native dllfunc(type,any:...);
|
||||||
|
|
||||||
//only use this with functions that pass a Trace
|
//only use this with functions that pass a Trace
|
||||||
// get: zero extra params - return int, one extra param = byref float or vector
|
// get: zero extra params - return int, one extra param = byref float or vector
|
||||||
|
|
|
@ -83,7 +83,7 @@ native fgets(file, buffer[], maxlength);
|
||||||
native fputs(file, const text[]);
|
native fputs(file, const text[]);
|
||||||
|
|
||||||
//Writes a line to the file
|
//Writes a line to the file
|
||||||
native fprintf(file, const fmt[], {Float,Sql,Result,_}:...);
|
native fprintf(file, const fmt[], any:...);
|
||||||
|
|
||||||
//Sets the current position in a file (see SEEK_ values above)
|
//Sets the current position in a file (see SEEK_ values above)
|
||||||
native fseek(file, position, start);
|
native fseek(file, position, start);
|
||||||
|
@ -97,7 +97,7 @@ native fputc(file, data);
|
||||||
native fungetc(file, data);
|
native fungetc(file, data);
|
||||||
|
|
||||||
//Return the size of a file
|
//Return the size of a file
|
||||||
native filesize(const filename[], {Float,Sql,Result,_}:...);
|
native filesize(const filename[], any:...);
|
||||||
|
|
||||||
//Attempts to remove a directory.
|
//Attempts to remove a directory.
|
||||||
//Note that you cannot remove a directory that has files on most
|
//Note that you cannot remove a directory that has files on most
|
||||||
|
|
|
@ -18,7 +18,7 @@ stock is_entity(id)
|
||||||
return is_valid_ent(id);
|
return is_valid_ent(id);
|
||||||
|
|
||||||
/* The end of the native is buffered incase the plugin is including an NS_VERSION (no longer supported), ignore it */
|
/* The end of the native is buffered incase the plugin is including an NS_VERSION (no longer supported), ignore it */
|
||||||
stock get_build(classname[], value, number=0,{Float,Sql,Result,_}:...)
|
stock get_build(classname[], value, number=0,any:...)
|
||||||
return ns_get_build(classname, value, number);
|
return ns_get_build(classname, value, number);
|
||||||
|
|
||||||
stock get_private_i(index, offset, linuxdiff=5)
|
stock get_private_i(index, offset, linuxdiff=5)
|
||||||
|
|
|
@ -34,7 +34,7 @@ native add(dest[],len,const src[],max=0);
|
||||||
* slower, so you should using a source string that is the same as
|
* slower, so you should using a source string that is the same as
|
||||||
* the destination.
|
* the destination.
|
||||||
*/
|
*/
|
||||||
native format(output[] ,len ,const format[] , {Float,Sql,Result,_}:...);
|
native format(output[] ,len ,const format[] , any:...);
|
||||||
|
|
||||||
/* Same as format(), except does not perform a "copy back" check.
|
/* Same as format(), except does not perform a "copy back" check.
|
||||||
* This means formatex() is faster, but DOES NOT ALLOW this type
|
* This means formatex() is faster, but DOES NOT ALLOW this type
|
||||||
|
@ -45,7 +45,7 @@ native format(output[] ,len ,const format[] , {Float,Sql,Result,_}:...);
|
||||||
* This is because the output is directly stored into "buffer",
|
* This is because the output is directly stored into "buffer",
|
||||||
* rather than copied back at the end.
|
* rather than copied back at the end.
|
||||||
*/
|
*/
|
||||||
native formatex(output[] ,len ,const format[] , {Float,Sql,Result,_}:...);
|
native formatex(output[] ,len ,const format[] , any:...);
|
||||||
|
|
||||||
/* Replacement for format_args. Much faster and %L compatible.
|
/* Replacement for format_args. Much faster and %L compatible.
|
||||||
* This works exactly like vsnprintf() from C.
|
* This works exactly like vsnprintf() from C.
|
||||||
|
|
456
plugins/testsuite/arraytest.sma
Normal file
456
plugins/testsuite/arraytest.sma
Normal file
|
@ -0,0 +1,456 @@
|
||||||
|
#include <amxmodx>
|
||||||
|
|
||||||
|
|
||||||
|
new __testnumber;
|
||||||
|
new errcount;
|
||||||
|
new __testfunc[32];
|
||||||
|
new __testfuncnum;
|
||||||
|
|
||||||
|
enum TestType
|
||||||
|
{
|
||||||
|
TT_Equal = 0,
|
||||||
|
TT_LessThan,
|
||||||
|
TT_GreaterThan,
|
||||||
|
TT_LessThanEqual,
|
||||||
|
TT_GreaterThanEqual,
|
||||||
|
TT_NotEqual
|
||||||
|
};
|
||||||
|
|
||||||
|
new TestWords[6][] = {
|
||||||
|
"==",
|
||||||
|
"<",
|
||||||
|
">",
|
||||||
|
"<=",
|
||||||
|
">=",
|
||||||
|
"!="
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
stock test(A,B=0,TestType:Type=TT_Equal)
|
||||||
|
{
|
||||||
|
++__testnumber;
|
||||||
|
|
||||||
|
new passed=0;
|
||||||
|
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case TT_Equal: if (A==B) passed=1;
|
||||||
|
case TT_LessThan: if (A<B) passed=1;
|
||||||
|
case TT_GreaterThan: if (A>B) passed=1;
|
||||||
|
case TT_LessThanEqual: if (A<=B) passed=1;
|
||||||
|
case TT_GreaterThanEqual: if (A>=B) passed=1;
|
||||||
|
case TT_NotEqual: if (A!=B) passed=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!passed)
|
||||||
|
{
|
||||||
|
log_amx("Failed test #%d (%d %s %d)",__testnumber,A,TestWords[_:Type],B);
|
||||||
|
errcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stock starttests(const startfunc[])
|
||||||
|
{
|
||||||
|
__testnumber=0;
|
||||||
|
errcount=0;
|
||||||
|
__testfuncnum=1;
|
||||||
|
server_print("Starting tests...");
|
||||||
|
formatex(__testfunc,sizeof(__testfunc)-1,"%s",startfunc);
|
||||||
|
|
||||||
|
new func[32];
|
||||||
|
formatex(func,sizeof(func)-1,"%s%d",__testfunc,__testfuncnum++);
|
||||||
|
set_task(0.1,func);
|
||||||
|
}
|
||||||
|
|
||||||
|
stock showres()
|
||||||
|
{
|
||||||
|
if (errcount==0)
|
||||||
|
{
|
||||||
|
new func[32];
|
||||||
|
formatex(func,sizeof(func)-1,"%s%d",__testfunc,__testfuncnum++);
|
||||||
|
if (get_func_id(func)==-1)
|
||||||
|
{
|
||||||
|
server_print("All tests ok!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
server_print("Test ok, moving on...");
|
||||||
|
|
||||||
|
set_task(0.1,func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
server_print("Test failed, aborting.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public plugin_init()
|
||||||
|
{
|
||||||
|
register_srvcmd("arraytest","arraytest");
|
||||||
|
}
|
||||||
|
|
||||||
|
public arraytest()
|
||||||
|
{
|
||||||
|
starttests("arraytest");
|
||||||
|
}
|
||||||
|
public arraytest1()
|
||||||
|
{
|
||||||
|
server_print("Testing 1000 iterations of 1-cell arrays...");
|
||||||
|
|
||||||
|
new Float:f;
|
||||||
|
new Array:a=ArrayCreate(1);
|
||||||
|
for (new i=0; i<1000; i++)
|
||||||
|
{
|
||||||
|
f=float(i);
|
||||||
|
ArrayPushCell(a,f);
|
||||||
|
}
|
||||||
|
new Float:r;
|
||||||
|
for (new i=0; i<1000; i++)
|
||||||
|
{
|
||||||
|
f=float(i);
|
||||||
|
ArrayGetCell(a,i,r);
|
||||||
|
|
||||||
|
// This is normally bad for float "casting", but in this case it should be fine.
|
||||||
|
test(_:f, _:r);
|
||||||
|
|
||||||
|
|
||||||
|
// Reset with inversed values
|
||||||
|
new g=_:f;
|
||||||
|
g=~g;
|
||||||
|
|
||||||
|
ArraySetCell(a,i,g);
|
||||||
|
|
||||||
|
ArrayGetCell(a,i,r);
|
||||||
|
|
||||||
|
test(g, _:r);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
stock bool:checkarray(const a[], const b[], size)
|
||||||
|
{
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
if (a[size]!=b[size])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
stock invarray(a[],size)
|
||||||
|
{
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
a[size] = ~a[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public arraytest2()
|
||||||
|
{
|
||||||
|
server_print("Testing 1000 iterations of 40-cell arrays...");
|
||||||
|
|
||||||
|
new Array:a=ArrayCreate(40);
|
||||||
|
new buff[40];
|
||||||
|
new buffb[40];
|
||||||
|
for (new i=0; i<1000; i++)
|
||||||
|
{
|
||||||
|
arrayset(buff,i,sizeof(buff));
|
||||||
|
|
||||||
|
ArrayPushArray(a, buff);
|
||||||
|
}
|
||||||
|
for (new i=0; i<1000; i++)
|
||||||
|
{
|
||||||
|
arrayset(buff, i, sizeof(buff));
|
||||||
|
|
||||||
|
ArrayGetArray(a, i, buffb);
|
||||||
|
|
||||||
|
test(_:checkarray(buff,buffb,sizeof(buff)),1);
|
||||||
|
|
||||||
|
// Now overwrite the array with inversed value
|
||||||
|
invarray(buff,sizeof(buff));
|
||||||
|
|
||||||
|
ArraySetArray(a, i, buff);
|
||||||
|
|
||||||
|
ArrayGetArray(a, i, buffb);
|
||||||
|
|
||||||
|
test(_:checkarray(buff,buffb,sizeof(buff)),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
public arraytest3()
|
||||||
|
{
|
||||||
|
server_print("Testing 1000 iterations of strings...");
|
||||||
|
|
||||||
|
// The string is 10 long, the string we're trying to pass is 20 long.
|
||||||
|
|
||||||
|
new Array:a=ArrayCreate(10);
|
||||||
|
|
||||||
|
new buff[20]="1234567890abcdefghi";
|
||||||
|
new buffb[20];
|
||||||
|
|
||||||
|
for (new i=0; i<1000; i++)
|
||||||
|
{
|
||||||
|
ArrayPushString(a, buff);
|
||||||
|
}
|
||||||
|
for (new i=0; i<1000; i++)
|
||||||
|
{
|
||||||
|
ArrayGetString(a, i, buffb, sizeof(buffb)-1);
|
||||||
|
|
||||||
|
test(strcmp(buffb,"123456789"),0);
|
||||||
|
|
||||||
|
ArraySetString(a, i, "9876543210");
|
||||||
|
|
||||||
|
ArrayGetString(a, i, buffb, sizeof(buffb)-1);
|
||||||
|
|
||||||
|
test(strcmp(buffb,"987654321"),0);
|
||||||
|
|
||||||
|
buffb[0]=0;
|
||||||
|
|
||||||
|
formatex(buffb,sizeof(buffb)-1,"%S", ArrayGetStringHandle(a, i));
|
||||||
|
|
||||||
|
test(strcmp(buffb, "987654321"),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
|
||||||
|
public sortcallback(Array:a, b, c)
|
||||||
|
{
|
||||||
|
static stra[40];
|
||||||
|
static strb[40];
|
||||||
|
|
||||||
|
ArrayGetString(a, b, stra, sizeof(stra)-1);
|
||||||
|
ArrayGetString(a, c, strb, sizeof(strb)-1);
|
||||||
|
return strcmp(stra,strb);
|
||||||
|
}
|
||||||
|
public arraytest4()
|
||||||
|
{
|
||||||
|
server_print("Testing sorting function...");
|
||||||
|
|
||||||
|
new Array:a=ArrayCreate(40);
|
||||||
|
|
||||||
|
ArrayPushString(a, "z");
|
||||||
|
ArrayPushString(a, "yz");
|
||||||
|
ArrayPushString(a, "xyz");
|
||||||
|
ArrayPushString(a, "wxyz");
|
||||||
|
ArrayPushString(a, "vwxyz");
|
||||||
|
ArrayPushString(a, "uvwxyz");
|
||||||
|
ArrayPushString(a, "tuvwxyz");
|
||||||
|
ArrayPushString(a, "stuvwxyz");
|
||||||
|
ArrayPushString(a, "rstuvwxyz");
|
||||||
|
ArrayPushString(a, "qrstuvwxyz");
|
||||||
|
ArrayPushString(a, "pqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "opqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "nopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "mnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "lmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "klmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "jklmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "ijklmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "hijklmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "ghijklmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "fghijklmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "efghijklmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "defghijklmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "cdefghijklmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "bcdefghijklmnopqrstuvwxyz");
|
||||||
|
ArrayPushString(a, "abcdefghijklmnopqrstuvwxyz");
|
||||||
|
|
||||||
|
new OldSize=ArraySize(a);
|
||||||
|
|
||||||
|
ArraySort(a, "sortcallback");
|
||||||
|
|
||||||
|
test(ArraySize(a),OldSize);
|
||||||
|
|
||||||
|
new buff[40];
|
||||||
|
|
||||||
|
ArrayGetString(a,0,buff,sizeof(buff)-1);
|
||||||
|
|
||||||
|
test(strcmp(buff,"abcdefghijklmnopqrstuvwxyz"),0);
|
||||||
|
|
||||||
|
ArrayGetString(a,25,buff,sizeof(buff)-1);
|
||||||
|
|
||||||
|
test(strcmp(buff,"z"),0);
|
||||||
|
|
||||||
|
|
||||||
|
new start='a';
|
||||||
|
|
||||||
|
for (new i=0;i<OldSize;i++)
|
||||||
|
{
|
||||||
|
ArrayGetString(a,i,buff,sizeof(buff)-1)
|
||||||
|
|
||||||
|
test(buff[0],start++);
|
||||||
|
}
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
public arraytest5()
|
||||||
|
{
|
||||||
|
server_print("Testing ArrayDeleteItem()...");
|
||||||
|
new Array:a=ArrayCreate(1);
|
||||||
|
|
||||||
|
new v;
|
||||||
|
|
||||||
|
for (new i=0; i<1000; i++)
|
||||||
|
{
|
||||||
|
ArrayPushCell(a, i);
|
||||||
|
}
|
||||||
|
for (new i=ArraySize(a) - 1; i>=0 ; i--)
|
||||||
|
{
|
||||||
|
if (i % 2 == 0)
|
||||||
|
{
|
||||||
|
ArrayDeleteItem(a, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test(ArraySize(a), 500);
|
||||||
|
for (new i=0; i< 500; i++)
|
||||||
|
{
|
||||||
|
ArrayGetCell(a, i, v);
|
||||||
|
|
||||||
|
// All items should be incrementing odd numbers
|
||||||
|
test(((i + 1) * 2) - 1, v);
|
||||||
|
|
||||||
|
// All remaining entries should be odd
|
||||||
|
test((v & 1), 1);
|
||||||
|
}
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
a=ArrayCreate(1);
|
||||||
|
// Repeat the same test, but check even numbers
|
||||||
|
for (new i=0; i<1000; i++)
|
||||||
|
{
|
||||||
|
ArrayPushCell(a, i);
|
||||||
|
}
|
||||||
|
for (new i=ArraySize(a) - 1; i>=0 ; i--)
|
||||||
|
{
|
||||||
|
if (i % 2 == 1)
|
||||||
|
{
|
||||||
|
ArrayDeleteItem(a, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test(ArraySize(a), 500);
|
||||||
|
for (new i=0; i< 500; i++)
|
||||||
|
{
|
||||||
|
ArrayGetCell(a, i, v);
|
||||||
|
|
||||||
|
// All items should be incrementing even numbers
|
||||||
|
test(((i + 1) * 2) - 2, v);
|
||||||
|
|
||||||
|
// All remaining entries should be even
|
||||||
|
test((v & 1), 0);
|
||||||
|
}
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
public arraytest6()
|
||||||
|
{
|
||||||
|
server_print("Testing ArrayInsertCellAfter()...");
|
||||||
|
|
||||||
|
new Array:a=ArrayCreate(1);
|
||||||
|
|
||||||
|
for (new i=0; i<10;i++)
|
||||||
|
{
|
||||||
|
ArrayPushCell(a, i);
|
||||||
|
new item=ArraySize(a)-1;
|
||||||
|
for (new j=0; j<10; j++)
|
||||||
|
{
|
||||||
|
ArrayInsertCellAfter(a, item + j, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test(ArraySize(a), 110);
|
||||||
|
|
||||||
|
new v;
|
||||||
|
for (new i=0; i<110; i++)
|
||||||
|
{
|
||||||
|
ArrayGetCell(a, i, v);
|
||||||
|
|
||||||
|
test(v, i / 10);
|
||||||
|
for (new j=0; j<10; j++)
|
||||||
|
{
|
||||||
|
ArrayGetCell(a, ++i, v);
|
||||||
|
test(v, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
public arraytest7()
|
||||||
|
{
|
||||||
|
server_print("Testing ArrayInsertCellBefore()...");
|
||||||
|
|
||||||
|
new Array:a=ArrayCreate(1);
|
||||||
|
|
||||||
|
for (new i=0; i<10;i++)
|
||||||
|
{
|
||||||
|
ArrayPushCell(a, i);
|
||||||
|
new item=ArraySize(a)-1;
|
||||||
|
for (new j=0; j<10; j++)
|
||||||
|
{
|
||||||
|
ArrayInsertCellBefore(a, item, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test(ArraySize(a), 110);
|
||||||
|
|
||||||
|
new v;
|
||||||
|
for (new i=0; i<110; i++)
|
||||||
|
{
|
||||||
|
for (new j=9; j>=0; j--)
|
||||||
|
{
|
||||||
|
ArrayGetCell(a, i++, v);
|
||||||
|
test(v, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayGetCell(a, i, v);
|
||||||
|
|
||||||
|
test(v, (i - 10) / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
public arraytest8()
|
||||||
|
{
|
||||||
|
server_print("Testing ArraySwap()...");
|
||||||
|
new Array:a=ArrayCreate(1);
|
||||||
|
|
||||||
|
for (new i=0; i<10; i++)
|
||||||
|
{
|
||||||
|
ArrayPushCell(a, i);
|
||||||
|
}
|
||||||
|
for (new i=0; i<5; i++)
|
||||||
|
{
|
||||||
|
ArraySwap(a, i, (10 - (i + 1)));
|
||||||
|
}
|
||||||
|
new v;
|
||||||
|
for (new i=0; i<5; i++)
|
||||||
|
{
|
||||||
|
ArrayGetCell(a, i, v);
|
||||||
|
|
||||||
|
test(v, (10 - (i + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user