static cell AMX_NATIVE_CALL n_strcat(AMX *amx, cell *params) { cell *cdest, *csrc; cdest = get_amxaddr(amx, params[1]); csrc = get_amxaddr(amx, params[2]); int num = params[3]; while (*cdest && num) { cdest++; num--; } if (!num) return 0; while (*csrc && num) { *cdest++ = *csrc++; num--; } *cdest = 0; return params[3] - num; }
// native SMCError:SMC_ParseFile(SMCParser:handle, const file[], &line = 0, &col = 0, any:data = 0); static cell AMX_NATIVE_CALL SMC_ParseFile(AMX *amx, cell *params) { ParseInfo *p = TextParsersHandles.lookup(params[1]); if (!p) { LogError(amx, AMX_ERR_NATIVE, "Invalid SMC parse handle (%d)", params[1]); return 0; } if (*params / sizeof(cell) >= 5) { p->data = params[5]; } int length; const char *file = build_pathname("%s", get_amxstring(amx, params[2], 0, length)); SMCStates states; SMCError p_err = textparsers->ParseFile_SMC(file, p, &states); *get_amxaddr(amx, params[3]) = states.line; *get_amxaddr(amx, params[4]) = states.col; return static_cast<cell>(p_err); }
static cell AMX_NATIVE_CALL add(AMX *amx, cell *params) /* 4 param */ { cell *src = get_amxaddr(amx, params[3]); cell *dest = get_amxaddr(amx, params[1]); cell *start = dest; int c = params[2], d = params[4]; while (*dest && c--) ++dest; if (d) { while (c-- && d-- && *src) *dest++ =* src++; *dest = 0; return (dest - start); } while (c-- && *src) *dest++ =* src++; *dest = 0; return (dest-start); }
static cell AMX_NATIVE_CALL equali(AMX *amx, cell *params) /* 3 param */ { cell *a = get_amxaddr(amx, params[1]); cell *b = get_amxaddr(amx, params[2]); int f, l, c = params[3]; if (c) { do { f = tolower(*a++); l = tolower(*b++); } while (--c && l && f && f == l); return (f - l) ? 0 : 1; } do { f = tolower(*a++); l = tolower(*b++); } while (f && f == l); return (f - l) ? 0 : 1; }
static cell AMX_NATIVE_CALL parse(AMX *amx, cell *params) /* 3 param */ { int inum = *params / sizeof(cell), iarg = 2, c; char* arg, *parse = get_amxstring(amx, params[1], 0, c); cell *cptr; int state; while (*parse) { arg = parse_arg(&parse,state); if (state) { if (inum <= iarg) return ((iarg - 2)>>1); cptr = get_amxaddr(amx, params[iarg++]); c = *get_amxaddr(amx, params[iarg++]); while (c-- && *arg) *cptr++ = (cell)*arg++; *cptr = 0; } } return ((iarg - 2)>>1); }
static cell AMX_NATIVE_CALL player_menu_info(AMX *amx, cell *params) { if (params[1] < 1 || params[1] > gpGlobals->maxClients) { LogError(amx, AMX_ERR_NATIVE, "Invalid player id %d", params[1]); return 0; } CPlayer *player = GET_PLAYER_POINTER_I(params[1]); if (!player->ingame) { LogError(amx, AMX_ERR_NATIVE, "Player %d is not ingame", params[1]); return 0; } cell *m = get_amxaddr(amx, params[2]); cell *n = get_amxaddr(amx, params[3]); *m = player->menu; *n = player->newmenu; if (params[0] / sizeof(cell) == 4) { cell *addr = get_amxaddr(amx, params[4]); *addr = player->page; } if ( (*m != 0 && *m != -1) || (*n != -1)) { return 1; } return 0; }
// native bool:INI_ParseFile(INIParser:handle, const file[], &line = 0, &col = 0, any:data = 0); static cell AMX_NATIVE_CALL INI_ParseFile(AMX *amx, cell *params) { ParseInfo *p = TextParsersHandles.lookup(params[1]); if (!p) { LogError(amx, AMX_ERR_NATIVE, "Invalid INI parse handle (%d)", params[1]); return 0; } int length; const char *file = build_pathname("%s", get_amxstring(amx, params[2], 0, length)); if (*params / sizeof(cell) >= 5) { p->data = params[5]; } unsigned int line, col; bool result = textparsers->ParseFile_INI(file, p, &line, &col); *get_amxaddr(amx, params[3]) = line; *get_amxaddr(amx, params[4]) = col; return result; }
static cell AMX_NATIVE_CALL vdformat(AMX *amx, cell *params) { if (!g_pCurNative || (g_pCurNative->amx != amx)) { LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); return 0; } if (g_pCurNative->style) { LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); return 0; } int vargPos = static_cast<int>(params[4]); int fargPos = static_cast<int>(params[3]); cell max = g_Params[0] / sizeof(cell); if (vargPos > (int)max + 1) { LogError(amx, AMX_ERR_NATIVE, "Invalid vararg parameter passed: %d", vargPos); return 0; } if (fargPos > (int)max + 1) { LogError(amx, AMX_ERR_NATIVE, "Invalid fmtarg parameter passed: %d", fargPos); return 0; } /* get destination info */ cell *fmt; if (fargPos == 0) { if (params[0] / sizeof(cell) != 5) { LogError(amx, AMX_ERR_NATIVE, "Expected fmtarg as fifth parameter, found none"); return 0; } fmt = get_amxaddr(amx, params[5]); } else { fmt = get_amxaddr(g_pCaller, g_Params[fargPos]); } cell *realdest = get_amxaddr(amx, params[1]); size_t maxlen = static_cast<size_t>(params[2]); cell *dest = realdest; /* if this is necessary... */ static cell cpbuf[4096]; dest = cpbuf; /* perform format */ size_t total = atcprintf(dest, maxlen, fmt, g_pCaller, g_Params, &vargPos); /* copy back */ memcpy(realdest, dest, (total+1) * sizeof(cell)); return total; }
static cell AMX_NATIVE_CALL formatex(AMX *amx, cell *params) { cell *buf = get_amxaddr(amx, params[1]); size_t maxlen = static_cast<size_t>(params[2]); cell *fmt = get_amxaddr(amx, params[3]); int param = 4; size_t total = atcprintf(buf, maxlen, fmt, amx, params, ¶m); return static_cast<cell>(total); }
static cell AMX_NATIVE_CALL vformat(AMX *amx, cell *params) { int vargPos = static_cast<int>(params[4]); /** get the parent parameter array */ AMX_HEADER *hdr = (AMX_HEADER *)amx->base; cell *local_params = (cell *)( (char *)amx->base + (cell)hdr->dat + (cell)amx->frm + (2 * sizeof(cell)) ); cell max = local_params[0] / sizeof(cell); if (vargPos > (int)max + 1) { LogError(amx, AMX_ERR_NATIVE, "Invalid vararg parameter passed: %d", vargPos); return 0; } /** * check for bounds clipping */ cell addr_start = params[1]; cell addr_end = addr_start + params[2]; bool copy = false; for (int i = vargPos; i <= max; i++) { //does this clip the bounds? if ( (local_params[i] >= addr_start) && (local_params[i] <= addr_end) ) { copy = true; break; } } /* get destination info */ cell *fmt = get_amxaddr(amx, params[3]); cell *realdest = get_amxaddr(amx, params[1]); size_t maxlen = static_cast<size_t>(params[2]); cell *dest = realdest; /* if this is necessary... */ static cell cpbuf[4096]; if (copy) dest = cpbuf; /* perform format */ size_t total = atcprintf(dest, maxlen, fmt, amx, local_params, &vargPos); /* copy back */ if (copy) { memcpy(realdest, dest, (total+1) * sizeof(cell)); } return total; }
bool CvarManager::BindCvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen) { if (varofs > amx->hlw) // If variable address is not inside global area, we can't bind it. { LogError(amx, AMX_ERR_NATIVE, "Cvars can only be bound to global variables"); return false; } int pluginId = g_plugins.findPluginFast(amx)->getId(); cell* address = get_amxaddr(amx, varofs); // To avoid unexpected behavior, probably better to error such situations. for (size_t i = 0; i < info->binds.length(); ++i) { CvarBind* bind = info->binds[i]; if (bind->pluginId == pluginId) { if (bind->varAddress == address) { LogError(amx, AMX_ERR_NATIVE, "A global variable can not be bound to multiple Cvars"); return false; } } } CvarBind* bind = new CvarBind(pluginId, type, get_amxaddr(amx, varofs), varlen); info->binds.append(bind); // Update right away variable with current cvar value. switch (type) { case CvarBind::CvarType_Int: *bind->varAddress = atoi(info->var->string); break; case CvarBind::CvarType_Float: *bind->varAddress = amx_ftoc(info->var->value); break; case CvarBind::CvarType_String: set_amxstring_simple(bind->varAddress, info->var->string, bind->varLength); break; } // Detour is disabled on map change. if (m_HookDetour) { m_HookDetour->EnableDetour(); } return true; }
static cell AMX_NATIVE_CALL copyc(AMX *amx, cell *params) /* 4 param */ { cell *src = get_amxaddr(amx, params[3]); cell *dest = get_amxaddr(amx, params[1]); cell *start = dest; int c = params[2]; cell ch = params[4]; while (c-- && *src && *src != ch) *dest++ =* src++; *dest = 0; return (dest - start); }
// native bool:TrieGetArray(Trie:handle, const key[], any:buff[], len, &size = 0); static cell AMX_NATIVE_CALL TrieGetArray(AMX *amx, cell *params) { CellTrie *t = TrieHandles.lookup(params[1]); if (!t) { LogError(amx, AMX_ERR_NATIVE, "Invalid map handle provided (%d)", params[1]); return 0; } if (params[4] < 0) { LogError(amx, AMX_ERR_NATIVE, "Invalid array size (%d)", params[4]); return 0; } int len; const char *key = get_amxstring(amx, params[2], 0, len); cell *pValue = get_amxaddr(amx, params[3]); cell *pSize = get_amxaddr(amx, params[5]); StringHashMap<Entry>::Result r = t->map.find(key); if (!r.found() || !r->value.isArray()) { return 0; } if (!r->value.array()) { *pSize = 0; return 1; } if (!params[4]) { return 1; } size_t length = r->value.arrayLength(); cell *base = r->value.array(); if (length > size_t(params[4])) *pSize = params[4]; else *pSize = length; memcpy(pValue, base, sizeof(cell) * pSize[0]); return 1; }
static cell AMX_NATIVE_CALL replace(AMX *amx, cell *params) /* 4 param */ { cell *text = get_amxaddr(amx, params[1]); cell len = params[2]; cell *what = get_amxaddr(amx, params[3]); cell *with = get_amxaddr(amx, params[4]); cell *textptr = text; int withLen = amxstring_len(with); int whatLen = amxstring_len(what); int textLen = amxstring_len(text); if (whatLen > textLen) return 0; if (whatLen < 1) { LogError(amx, AMX_ERR_NATIVE, "No search string specified."); return 0; } if (textLen - whatLen + withLen > len) { LogError(amx, AMX_ERR_NATIVE, "replace() buffer not big enough (%d>=%d)", (textLen - whatLen + withLen), len); return 0; } cell browsed = 0; while (*text && (browsed <= (textLen-whatLen))) { if (*text == *what) { if (fastcellcmp(text, what, whatLen)) { cell *saveptr = text + whatLen; cell restlen = textLen - (browsed + whatLen); textptr = text + withLen; memmove(textptr, saveptr, (restlen + 1) * sizeof(cell)); memcpy(text, with, withLen * sizeof(cell)); return (textLen - whatLen + withLen); } } text++; browsed++; } return 0; }
// native ArrayFindString(Array:which, const item[]); static cell AMX_NATIVE_CALL ArrayFindString(AMX* amx, cell* params) { CellArray* vec = HandleToVector(amx, params[1]); if (vec == NULL) { return -1; } cell *b, *a = get_amxaddr(amx, params[2]); size_t cellcount = vec->blocksize(); size_t a_len = ke::Max(1, amxstring_len(a)); size_t len = a_len > cellcount ? cellcount : a_len; for (size_t i = 0; i < vec->size(); i++) { b = vec->at(i); if (fastcellcmp(a, b, len)) { return static_cast<cell>(i); } } return -1; }
// native ArraySetArray(Array:which, item, const any:input[], size =-1); static cell AMX_NATIVE_CALL ArraySetArray(AMX* amx, cell* params) { CellArray* vec = ArrayHandles.lookup(params[1]); if (!vec) { LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]); return 0; } size_t idx = (size_t)params[2]; if (idx >= vec->size()) { LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); return 0; } cell *blk = vec->at(idx); size_t indexes = vec->blocksize(); if (*params / sizeof(cell) == 4) { if (params[4] != -1 && (size_t)params[4] <= vec->blocksize()) { indexes = params[4]; } } cell *addr = get_amxaddr(amx, params[3]); memcpy(blk, addr, sizeof(cell) * indexes); return indexes; }
// native bool:PopStackArray(Stack:handle, any:buffer[], size=-1); static cell AMX_NATIVE_CALL PopStackArray(AMX* amx, cell* params) { CellArray* vec = HandleToVector(amx, params[1]); if (vec == NULL) { return 0; } if (vec->size() == 0) { return 0; } size_t idx = vec->size() - 1; cell *blk = vec->at(idx); size_t indexes = vec->blocksize(); if (params[3] != -1 && (size_t)params[3] <= vec->blocksize()) { indexes = params[3]; } cell *addr = get_amxaddr(amx, params[2]); memcpy(addr, blk, indexes * sizeof(cell)); vec->remove(idx); return 1; }
// native ArrayGetArray(Array:which, item, any:output[], size = -1); static cell AMX_NATIVE_CALL ArrayGetArray(AMX* amx, cell* params) { CellArray* vec = HandleToVector(amx, params[1]); if (vec == NULL) { return 0; } size_t idx = (size_t)params[2]; if (idx >= vec->size()) { LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); return 0; } cell *blk = vec->at(idx); size_t indexes = vec->blocksize(); if (*params / sizeof(cell) == 4) { if (params[4] != -1 && (size_t)params[4] <= vec->blocksize()) { indexes = params[4]; } } cell *addr = get_amxaddr(amx, params[3]); memcpy(addr, blk, sizeof(cell) * indexes); return indexes; }
// native ArrayPushArray(Array:which, const any:input[], size = -1); static cell AMX_NATIVE_CALL ArrayPushArray(AMX* amx, cell* params) { CellArray* vec = ArrayHandles.lookup(params[1]); if (!vec) { LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]); return 0; } cell *blk = vec->push(); if (!blk) { LogError(amx, AMX_ERR_NATIVE, "Failed to grow array"); return 0; } cell *addr = get_amxaddr(amx, params[2]); size_t indexes = vec->blocksize(); if (*params / sizeof(cell) == 3) { if (params[3] != -1 && (size_t)params[3] <= vec->blocksize()) { indexes = params[3]; } } memcpy(blk, addr, sizeof(cell) * indexes); return static_cast<cell>((vec->size() - 1)); }
// native bool:TrieGetCell(Trie:handle, const key[], &any:value); static cell AMX_NATIVE_CALL TrieGetCell(AMX *amx, cell *params) { CellTrie *t = TrieHandles.lookup(params[1]); if (!t) { LogError(amx, AMX_ERR_NATIVE, "Invalid map handle provided (%d)", params[1]); return 0; } int len; const char *key = get_amxstring(amx, params[2], 0, len); StringHashMap<Entry>::Result r = t->map.find(key); if (!r.found()) { return 0; } cell *ptr = get_amxaddr(amx, params[3]); if (r->value.isCell()) { *ptr = r->value.cell_(); return 1; } return 0; }
// native bool:TrieGetString(Trie:handle, const key[], buff[], len, &size = 0); static cell AMX_NATIVE_CALL TrieGetString(AMX *amx, cell *params) { CellTrie *t = TrieHandles.lookup(params[1]); if (!t) { LogError(amx, AMX_ERR_NATIVE, "Invalid map handle provided (%d)", params[1]); return 0; } if (params[4] < 0) { LogError(amx, AMX_ERR_NATIVE, "Invalid buffer size (%d)", params[4]); return 0; } int len; const char *key = get_amxstring(amx, params[2], 0, len); cell *pSize = get_amxaddr(amx, params[5]); StringHashMap<Entry>::Result r = t->map.find(key); if (!r.found() || !r->value.isString()) { return 0; } *pSize = (cell)set_amxstring_utf8(amx, params[3], r->value.chars(), strlen(r->value.chars()), params[4]); return 1; }
char* format_amxstring(AMX *amx, cell *params, int parm, int &len) { static char outbuf[4096]; cell *addr = get_amxaddr(amx, params[parm++]); len = atcprintf(outbuf, sizeof(outbuf)-1, addr, amx, params, &parm); return outbuf; }
// native bool:PopStackString(Stack:handle, buffer[], maxlength, &written = 0); static cell AMX_NATIVE_CALL PopStackString(AMX* amx, cell* params) { CellArray* vec = ArrayHandles.lookup(params[1]); if (!vec) { LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]); return 0; } if (vec->size() == 0) { return 0; } size_t idx = vec->size() - 1; cell *blk = vec->at(idx); int numWritten = set_amxstring_utf8(amx, params[2], blk, amxstring_len(blk), params[3]); *get_amxaddr(amx, params[4]) = numWritten; vec->remove(idx); return 1; }
// native PushStackArray(Stack:handle, const any:values[], size= -1); static cell AMX_NATIVE_CALL PushStackArray(AMX* amx, cell* params) { CellArray* vec = ArrayHandles.lookup(params[1]); if (!vec) { LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]); return 0; } cell *blk = vec->push(); if (!blk) { LogError(amx, AMX_ERR_NATIVE, "Failed to grow stack"); return 0; } cell *addr = get_amxaddr(amx, params[2]); size_t indexes = vec->blocksize(); if (params[3] != -1 && (size_t)params[3] <= vec->blocksize()) { indexes = params[3]; } memcpy(blk, addr, indexes * sizeof(cell)); return 1; }
// native bool:PopStackArray(Stack:handle, any:buffer[], size=-1); static cell AMX_NATIVE_CALL PopStackArray(AMX* amx, cell* params) { CellArray* vec = ArrayHandles.lookup(params[1]); if (!vec) { LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]); return 0; } if (vec->size() == 0) { return 0; } size_t idx = vec->size() - 1; cell *blk = vec->at(idx); size_t indexes = vec->blocksize(); if (params[3] != -1 && (size_t)params[3] <= vec->blocksize()) { indexes = params[3]; } cell *addr = get_amxaddr(amx, params[2]); memcpy(addr, blk, indexes * sizeof(cell)); vec->remove(idx); return 1; }
// native ArrayFindString(Array:which, const item[]); static cell AMX_NATIVE_CALL ArrayFindString(AMX* amx, cell* params) { CellArray* vec = ArrayHandles.lookup(params[1]); if (!vec) { LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]); return -1; } cell *b, *a = get_amxaddr(amx, params[2]); size_t cellcount = vec->blocksize(); size_t a_len = ke::Max(1, amxstring_len(a)); size_t len = a_len > cellcount ? cellcount : a_len; for (size_t i = 0; i < vec->size(); i++) { b = vec->at(i); if (fastcellcmp(a, b, len)) { return static_cast<cell>(i); } } return -1; }
static cell AMX_NATIVE_CALL copy(AMX *amx, cell *params) /* 4 param */ { cell *src = get_amxaddr(amx, params[3]); int c = params[2]; cell *dest = get_amxaddr(amx, params[1]); cell *start = dest; while (c-- && *src) { *dest++ = *src++; } *dest = '\0'; return (dest - start); }
// native PushStackArray(Stack:handle, const any:values[], size= -1); static cell AMX_NATIVE_CALL PushStackArray(AMX* amx, cell* params) { CellArray* vec = HandleToVector(amx, params[1]); if (vec == NULL) { return 0; } cell *blk = vec->push(); if (!blk) { LogError(amx, AMX_ERR_NATIVE, "Failed to grow stack"); return 0; } cell *addr = get_amxaddr(amx, params[2]); size_t indexes = vec->blocksize(); if (params[3] != -1 && (size_t)params[3] <= vec->blocksize()) { indexes = params[3]; } memcpy(blk, addr, indexes * sizeof(cell)); return 1; }
static cell _message_begin(AMX *amx, cell *params, bool useFloat) /* 4 param */ { int numparam = *params / sizeof(cell); float vecOrigin[3]; cell *cpOrigin; if (params[2] < 1 || ((params[2] > 63) // maximal number of engine messages && !GET_USER_MSG_NAME(PLID, params[2], NULL))) { LogError(amx, AMX_ERR_NATIVE, "Plugin called message_begin with an invalid message id (%d).", params[2]); return 0; } switch (params[1]) { case MSG_BROADCAST: case MSG_ALL: case MSG_SPEC: case MSG_INIT: MESSAGE_BEGIN(params[1], params[2], NULL); break; case MSG_PVS: case MSG_PAS: case MSG_PVS_R: case MSG_PAS_R: if (numparam < 3) { LogError(amx, AMX_ERR_NATIVE, "Invalid number of parameters passed"); return 0; } cpOrigin = get_amxaddr(amx, params[3]); if (!useFloat) { vecOrigin[0] = static_cast<float>(*cpOrigin); vecOrigin[1] = static_cast<float>(*(cpOrigin + 1)); vecOrigin[2] = static_cast<float>(*(cpOrigin + 2)); } else { vecOrigin[0] = amx_ctof(*cpOrigin); vecOrigin[1] = amx_ctof(*(cpOrigin + 1)); vecOrigin[2] = amx_ctof(*(cpOrigin + 2)); } MESSAGE_BEGIN(params[1], params[2], vecOrigin); break; case MSG_ONE_UNRELIABLE: case MSG_ONE: if (numparam < 4) { LogError(amx, AMX_ERR_NATIVE, "Invalid number of parameters passed"); return 0; } MESSAGE_BEGIN(params[1], params[2], NULL, INDEXENT(params[4])); break; } return 1; }
char *get_amxstring_null(AMX *amx, cell amx_addr, int id, int& len) { if (get_amxaddr(amx, amx_addr) == g_plugins.findPluginFast(amx)->getNullStringOfs()) { return nullptr; } return get_amxstring(amx, amx_addr, id, len); }