//native regex_replace(Regex:pattern, string[], maxLen, const replace[], flags = REGEX_FORMAT_DEFAULT, &errcode = 0); static cell AMX_NATIVE_CALL regex_replace(AMX *amx, cell *params) { int id = params[1] - 1; if (id >= (int)PEL.length() || id < 0 || PEL[id]->isFree()) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid regex handle %d", id); return 0; } int textLen, replaceLen; char *text = MF_GetAmxString(amx, params[2], 0, &textLen); const char *replace = MF_GetAmxString(amx, params[4], 1, &replaceLen); cell *erroCode = MF_GetAmxAddr(amx, params[6]); RegEx *x = PEL[id]; int e = x->Replace(text, params[3] + 1, replace, replaceLen, params[5]); if (e == -1) { *erroCode = x->mErrorOffset; x->ClearMatch(); return -2; } else if (e == 0) { *erroCode = 0; x->ClearMatch(); return 0; } MF_SetAmxString(amx, params[2], text, params[3]); return e; }
static cell AMX_NATIVE_CALL find_ent_by_model(AMX *amx, cell *params) { int iStart = params[1]; int iLength, iLength2; char *szClass = MF_GetAmxString(amx, params[2], 0, &iLength); char *szModel = MF_GetAmxString(amx, params[3], 1, &iLength2); edict_t *pStart; if (iStart == -1) { pStart = NULL; } else { if (!is_ent_valid(iStart)) pStart = NULL; else pStart = INDEXENT2(iStart); } edict_t *pEdict = FIND_ENTITY_BY_STRING(pStart, "classname", szClass); const char *check; while (pEdict && !FNullEnt(pEdict)) { check = STRING(pEdict->v.model); if (!check || strcmp(check, szModel)) pEdict = FIND_ENTITY_BY_STRING(pEdict, "classname", szClass); else return ENTINDEX(pEdict); } return 0; }
// native socket_listen_t( rc, hostname, port, protocol, recvhandler ) // Give access to iMaxConnections also ? static cell AMX_NATIVE_CALL socket_listen_t(AMX *amx, cell *params) /* 5 param */ { if( !params[1] ) return -1; // Get SocketThread form param[1] CThreadedSocketItem* SocketThread = (CThreadedSocketItem *)params[1]; int len; char* szTempHostnam = MF_GetAmxString(amx,params[2],0,&len); if( SocketThread->Hostname != NULL ) { delete [] SocketThread->Hostname; SocketThread->Hostname = NULL; } SocketThread->Hostname = new char [len+1]; // Copy Hostname strcpy( SocketThread->Hostname, szTempHostnam ); SocketThread->Hostname[len] = '\0'; SocketThread->port = params[3]; SocketThread->protocol = params[4]; // Register Forward and save fwdID in fid array SocketThread->fIDs[FID_LISTEN] = MF_RegisterSPForwardByName(amx, MF_GetAmxString(amx, params[5], 0, &len), FP_CELL, FP_CELL, FP_DONE); if( SocketThread->fIDs[FID_LISTEN] < 0 ) { return -2; // Could not find Public CallBack function to register it } // Since all the required data is set, Run the thread in required state SocketThread->ThreadState(STATE_LISTEN); return 0; }
static cell AMX_NATIVE_CALL register_touch(AMX *amx, cell *params) { int len; char *Toucher = MF_GetAmxString(amx, params[1], 0, &len); char *Touched = MF_GetAmxString(amx, params[2], 1, &len); Touch *p = new Touch; if (!strlen(Toucher) || strcmp(Toucher, "*")==0) { p->Toucher.assign(""); } else { p->Toucher.assign(Toucher); } if (!strlen(Touched) || strcmp(Touched, "*")==0) { p->Touched.assign(""); } else { p->Touched.assign(Touched); } p->Forward = MF_RegisterSPForwardByName(amx, MF_GetAmxString(amx, params[3], 2, &len), FP_CELL, FP_CELL, FP_DONE); Touches.push_back(p); if (!g_pFunctionTable->pfnTouch) g_pFunctionTable->pfnTouch=pfnTouch; return p->Forward; }
// name,logname,melee=0 static cell AMX_NATIVE_CALL register_cwpn(AMX *amx, cell *params) { int i; bool bFree = false; for(i = DODMAX_WEAPONS - DODMAX_CUSTOMWPNS; i < DODMAX_WEAPONS; i++) { if(!weaponData[i].needcheck) { bFree = true; break; } } if(!bFree) return 0; int iLen; char *szName = MF_GetAmxString(amx, params[1], 0, &iLen); char *szLogName = MF_GetAmxString(amx, params[3], 0, &iLen); strcpy(weaponData[i].name,szName); strcpy(weaponData[i].logname,szLogName); weaponData[i].needcheck = true; weaponData[i].melee = params[2] ? true:false; return i; }
static cell AMX_NATIVE_CALL set_kvd(AMX *amx, cell *params) { KVD_Wrapper *kvdw; KeyValueData *kvd; if (params[1] == 0) kvdw = &g_kvd_glb; else kvdw = reinterpret_cast<KVD_Wrapper *>(params[1]); kvd = kvdw->kvd; if (*params / sizeof(cell) < 3) { MF_LogError(amx, AMX_ERR_NATIVE, "No data passed"); return 0; } cell *ptr = MF_GetAmxAddr(amx, params[3]); int len; switch (params[2]) { case KV_fHandled: { kvd->fHandled = (int)*ptr; return 1; break; } case KV_ClassName: { kvdw->cls = MF_GetAmxString(amx, params[3], 0, &len); kvd->szClassName = const_cast<char *>(kvdw->cls.chars()); return 1; break; } case KV_KeyName: { kvdw->key = MF_GetAmxString(amx, params[3], 0, &len); kvd->szKeyName = const_cast<char *>(kvdw->key.chars()); return 1; break; } case KV_Value: { kvdw->val = MF_GetAmxString(amx, params[3], 0, &len); kvd->szValue = const_cast<char *>(kvdw->val.chars()); return 1; break; } } MF_LogError(amx, AMX_ERR_NATIVE, "Invalid KeyValueData member: %d", params[2]); return 0; }
cell Call_Int_Str_Str(AMX* amx, cell* params) { SETUP(2); char *sz3=MF_GetAmxString(amx, params[3], 0, NULL); char *sz4=MF_GetAmxString(amx, params[4], 1, NULL); #if defined(_WIN32) return reinterpret_cast<int (__fastcall *)(void*, int, const char *, const char *)>(__func)(pv, 0, sz3, sz4); #elif defined(__linux__) || defined(__APPLE__) return reinterpret_cast<int (*)(void *, const char *, const char *)>(__func)(pv, sz3, sz4); #endif }
// SetLights, this sets the lights for the map. //(vexd) static cell AMX_NATIVE_CALL set_lights(AMX *amx, cell *params) { int iLength; char *szLights = MF_GetAmxString(amx, params[1], 0, &iLength); if (FStrEq(szLights, "#OFF")) { glinfo.bCheckLights = false; g_pFunctionTable_Post->pfnStartFrame = NULL; memset(glinfo.szLastLights, 0x0, 128); (g_engfuncs.pfnLightStyle)(0, glinfo.szRealLights); return 1; } g_pFunctionTable_Post->pfnStartFrame = StartFrame_Post; glinfo.bCheckLights = true; //Reset LastLights memset(glinfo.szLastLights, 0x0, 128); //Store the previous lighting. memcpy(glinfo.szLastLights, szLights, strlen(szLights)); (g_engfuncs.pfnLightStyle)(0, szLights); // These make it so that players/weaponmodels look like whatever the lighting is // at. otherwise it would color players under the skybox to these values. SERVER_COMMAND("sv_skycolor_r 0\n"); SERVER_COMMAND("sv_skycolor_g 0\n"); SERVER_COMMAND("sv_skycolor_b 0\n"); return 1; }
static cell AMX_NATIVE_CALL SQL_QuoteString(AMX *amx, cell *params) { int len; char *str = MF_GetAmxString(amx, params[4], 0, &len); size_t newsize; static char buffer[8192]; if (params[1] != 0) { IDatabase *pDb = (IDatabase *)GetHandle(params[1], Handle_Database); if (!pDb) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid database handle: %d", params[1]); return 0; } if (pDb->QuoteString(str, buffer, sizeof(buffer)-1, &newsize) == 0) { MF_SetAmxString(amx, params[2], buffer, params[3]); return newsize; } else { return -1; } } else { if (g_Sqlite.QuoteString(str, buffer, sizeof(buffer)-1, &newsize) == 0) { MF_SetAmxString(amx, params[2], buffer, params[3]); return newsize; } else { return -1; } } }
static cell AMX_NATIVE_CALL SQL_MakeDbTuple(AMX *amx, cell *params) { SQL_Connection *sql = new SQL_Connection; int len; sql->port = 0; sql->host = strdup(""); sql->user = strdup(""); sql->pass = strdup(""); char *db = MF_GetAmxString(amx, params[4], 0, &len); char path[255]; FILE *fp; MF_BuildPathnameR(path, sizeof(path)-1, "%s", db); if ((fp=fopen(path, "rb"))) { fclose(fp); sql->db = strdup(path); } else { MF_BuildPathnameR(path, sizeof(path)-1, "%s/sqlite3/%s.sq3", MF_GetLocalInfo("amxx_datadir", "addons/amxmodx/data"), db); sql->db = strdup(path); } unsigned int num = MakeHandle(sql, Handle_Connection, FreeConnection); return num; }
// ns_giveiteM(id,"item"); static cell AMX_NATIVE_CALL ns_giveitem(AMX *amx, cell *params) { CreatePlayerPointer(amx,params[1]); char *classname = MF_GetAmxString(amx,params[2],0,NULL); if (!player->IsConnected()) { return 0; } if (player->GetPev()->deadflag > 0) { return 0; } edict_t *object=CREATE_NAMED_ENTITY(ALLOC_STRING2(classname)); if (!object) { MF_LogError(amx, AMX_ERR_NATIVE, "Error creating entity \"%s\"", classname); return 0; } SET_ORIGIN(object,player->GetPev()->origin); // move to player gpGamedllFuncs->dllapi_table->pfnSpawn(object); // emulate spawn object->v.flags |= FL_ONGROUND; // make it think it's touched the ground gpGamedllFuncs->dllapi_table->pfnThink(object); // gpGamedllFuncs->dllapi_table->pfnTouch(object,player->GetEdict()); // give it to the player return 1; }
cell Call_Void_Str_Str_Int(AMX *amx, cell *params) { SETUP(3); char *sz3=MF_GetAmxString(amx, params[3], 0, NULL); char *sz4=MF_GetAmxString(amx, params[4], 1, NULL); int i5=*MF_GetAmxAddr(amx, params[5]); #if defined(_WIN32) reinterpret_cast<void (__fastcall *)(void*, int, const char *, const char *, int)>(__func)(pv, 0, sz3, sz4, i5); #elif defined(__linux__) || defined(__APPLE__) reinterpret_cast<void (*)(void *, const char *, const char *, int)>(__func)(pv, sz3, sz4, i5); #endif return 1; }
static cell AMX_NATIVE_CALL SQL_FieldNameToNum(AMX *amx, cell *params) { AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query); if (!qInfo) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid query handle: %d", params[1]); return 0; } IResultSet *rs = qInfo->info.rs; if (!rs) { MF_LogError(amx, AMX_ERR_NATIVE, "No result set in this query!"); return 0; } int len; char *namewa = MF_GetAmxString(amx, params[2], 0, &len); unsigned int columnId; if (!rs->FieldNameToNum(namewa, &columnId)) { return -1; } return columnId; }
static cell AMX_NATIVE_CALL csdm_reload_cfg(AMX *amx, cell *params) { char file[255]; file[0] = '\0'; if (params[0] / sizeof(cell) != 0) { int len; char *str = MF_GetAmxString(amx, params[1], 0, &len); if (str[0] != '\0') { MF_BuildPathnameR(file, sizeof(file)-1, "%s/%s", LOCALINFO("amxx_configsdir"), str); } } if (file[0] == '\0') { MF_BuildPathnameR(file, sizeof(file)-1, "%s/csdm.cfg", LOCALINFO("amxx_configsdir")); } if (g_Config.ReadConfig(file) != Config_Ok) { MF_Log("Could not read config file: %s", file); return 0; } return 1; }
static cell AMX_NATIVE_CALL fm_return(AMX *amx, cell *params) { int len; switch (params[1]) { case FMV_STRING: { mStringResult = STRING(ALLOC_STRING(MF_GetAmxString(amx, params[2], 0 ,&len))); break; } case FMV_FLOAT: { mFloatResult = amx_ctof(*(MF_GetAmxAddr(amx,params[2]))); break; } case FMV_CELL: { mCellResult = *(MF_GetAmxAddr(amx,params[2])); break; } default: { return 0; break; } } retType = params[1]; return 1; }
// native geoip_region_code(const ip[], result[], len); static cell AMX_NATIVE_CALL amx_geoip_region_code(AMX *amx, cell *params) { int length; int finalLength = 0; char code[12]; // This should be largely enough to hold xx-yyyy and more if needed. char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length)); const char *pathCountry[] = { "country", "iso_code", NULL }; const char *countryCode = lookupString(ip, pathCountry, &length); if (countryCode) { finalLength = length + 1; // + 1 for dash. ke::SafeSprintf(code, finalLength + 1, "%s-", countryCode); // + EOS. const char *pathRegion[] = { "subdivisions", "0", "iso_code", NULL }; // First result. const char *regionCode = lookupString(ip, pathRegion, &length); if (regionCode) { finalLength += length; strncat(code, regionCode, length); } else { finalLength = 0; } } return MF_SetAmxString(amx, params[2], finalLength ? code : "", ke::Min(finalLength, params[3])); }
// native bool:geoip_code3_ex(const ip[], result[4]); static cell AMX_NATIVE_CALL amx_geoip_code3_ex(AMX *amx, cell *params) { int length; char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length)); const char *path[] = { "country", "iso_code", NULL }; const char *code = lookupString(ip, path, &length); if (!code) { return 0; } for (size_t i = 0; i < ARRAYSIZE(GeoIPCountryCode); ++i) { if (!strncmp(code, GeoIPCountryCode[i], 2)) { code = GeoIPCountryCode3[i]; break; } } MF_SetAmxString(amx, params[2], code, 3); return 1; }
static cell AMX_NATIVE_CALL SQL_SetAffinity(AMX *amx, cell *params) { int len; char *str = MF_GetAmxString(amx, params[1], 0, &len); if (!str[0]) { return 1; } if (stricmp(str, g_Sqlite.NameString()) == 0) { return 1; } SqlFunctions *pFuncs = (SqlFunctions *)MF_RequestFunction(SQL_DRIVER_FUNC); while (pFuncs) { if (pFuncs->driver->IsCompatDriver(str)) { return pFuncs->set_affinity(amx); } pFuncs = pFuncs->prev; } return 0; }
static cell AMX_NATIVE_CALL find_ent_by_owner(AMX *amx, cell *params) // native find_ent_by_owner(start_from_ent, classname[], owner_index); = 3 params { int iEnt = params[1]; int oEnt = params[3]; // Check index to start searching at, 0 must be possible for iEnt. CHECK_ENTITY_SIMPLE(oEnt); edict_t *pEnt = INDEXENT2(iEnt); edict_t *entOwner = INDEXENT2(oEnt); //optional fourth parameter is for jghg2 compatibility const char* sCategory = NULL; switch(params[4]){ case 1: sCategory = "target"; break; case 2: sCategory = "targetname"; break; default: sCategory = "classname"; } // No need to check if there is a real ent where entOwner points at since we don't access it anyway. int len; char* classname = MF_GetAmxString(amx, params[2], 0, &len); while (true) { pEnt = FIND_ENTITY_BY_STRING(pEnt, sCategory, classname); if (FNullEnt(pEnt)) // break and return 0 if bad break; else if (pEnt->v.owner == entOwner) // compare pointers return ENTINDEX(pEnt); } // If it comes here, the while loop ended because an ent failed (FNullEnt() == true) return 0; }
static cell AMX_NATIVE_CALL csdm_setstyle(AMX *amx, cell *params) { int len; char *name = MF_GetAmxString(amx, params[1], 0, &len); if (strcmp(name, "none") == 0) { g_SpawnMethod = -1; return 1; } SpawnMethod *pSpawn = NULL; for (size_t i=0; i<g_SpawnMngr.Spawns(); i++) { pSpawn = g_SpawnMngr.GetSpawn(i); if (strcmpi(pSpawn->GetName(), name) == 0) { g_SpawnMethod = i; return 1; } } return 0; }
static cell AMX_NATIVE_CALL register_think(AMX *amx, cell *params) { int len; EntClass *p = new EntClass; const char *clsname = MF_GetAmxString(amx, params[1], 0, &len); p->Class.assign(clsname); p->Forward = MF_RegisterSPForwardByName(amx, MF_GetAmxString(amx, params[2], 0, &len), FP_CELL, FP_DONE); Thinks.push_back(p); if (!g_pFunctionTable->pfnThink) g_pFunctionTable->pfnThink=Think; return p->Forward; }
static cell AMX_NATIVE_CALL csdm_reg_cfg(AMX *amx, cell *params) { int length; char *setting = MF_GetAmxString(amx, params[1], 0, &length); char *func = MF_GetAmxString(amx, params[2], 1, &length); int forward = MF_RegisterSPForwardByName(amx, func, FP_CELL, FP_STRING, FP_STRING, FP_DONE); if (forward < 1) { MF_LogError(amx, AMX_ERR_NATIVE, "Public function \"%s\" not found", func); return 0; } g_Config.AddHook(setting, forward); return 1; }
static cell AMX_NATIVE_CALL get_keyvalue(AMX *amx, cell *params) { int idx = params[1]; CHECK_ENTITY(idx); edict_t *pEntity = INDEXENT2(idx); int iLength=0; char *char1 = MF_GetAmxString(amx, params[2], 1, &iLength); return MF_SetAmxString(amx, params[3], INFO_KEY_VALUE(INFO_KEY_BUFFER(pEntity),char1), params[4]); }
// native socket_open(_hostname[], _port, _protocol = SOCKET_TCP, &_error); static cell AMX_NATIVE_CALL socket_open(AMX *amx, cell *params) /* 2 param */ { unsigned int port = params[2]; int len; char* hostname = MF_GetAmxString(amx,params[1],0,&len); // Get the hostname from AMX cell *err = MF_GetAmxAddr(amx, params[4]); if(len == 0) { // just to prevent to work with a nonset hostname *err = 2; // server unknown return -1; } *err = 0; // params[4] is error backchannel struct sockaddr_in server; struct hostent *host_info; unsigned long addr; int sock=-1; int contr; // Create a Socket sock = socket(AF_INET, params[3]==SOCKET_TCP?SOCK_STREAM:SOCK_DGRAM, 0); if (sock < 0) { // Error, couldn't create a socket, so set an error and return. *err = 1; return -1; } // Clear the server structure (set everything to 0) memset( &server, 0, sizeof (server)); // Test the hostname, and resolve if needed if ((addr = inet_addr(hostname)) != INADDR_NONE) { // seems like hostname is a numeric ip, so put it into the structure memcpy( (char *)&server.sin_addr, &addr, sizeof(addr)); } else { // hostname is a domain, so resolve it to an ip host_info = gethostbyname(hostname); if (host_info == NULL) { // an error occured, the hostname is unknown *err = 2; // server unknown return -1; } // If not, put it in the Server structure memcpy( (char *)&server.sin_addr, host_info->h_addr, host_info->h_length); } // Set the type of the Socket server.sin_family = AF_INET; // Change the port to network byte order, and put it into the structure server.sin_port = htons(port); // Not, let's try to open a connection to the server contr = connect(sock, (struct sockaddr*)&server, sizeof( server)); if (contr < 0) { // If an error occured cancel *err = 3; //error while connecting return -1; } // Everything went well, so return the socket return sock; }
cell Call_Int_Str_Str_Int_Str_Int_Int(AMX* amx, cell* params) { SETUP(6); const char *sz3=STRING(ALLOC_STRING(MF_GetAmxString(amx, params[3], 0, NULL))); const char *sz4=STRING(ALLOC_STRING(MF_GetAmxString(amx, params[4], 1, NULL))); const char *sz6=STRING(ALLOC_STRING(MF_GetAmxString(amx, params[6], 2, NULL))); int i5=*MF_GetAmxAddr(amx, params[5]); int i7=*MF_GetAmxAddr(amx, params[7]); int i8=*MF_GetAmxAddr(amx, params[8]); #if defined(_WIN32) return reinterpret_cast<int (__fastcall *)(void*, int, const char *, const char *, int, const char *, int, int)>(__func)(pv, 0, sz3, sz4, i5, sz6, i7, i8); #elif defined(__linux__) || defined(__APPLE__) return reinterpret_cast<int (*)(void *, const char *, const char *, int, const char *, int, int)>(__func)(pv, sz3, sz4, i5, sz6, i7, i8); #endif }
//shamelessly pulled from fun static cell AMX_NATIVE_CALL csdm_give_item(AMX *amx, cell *params) // native give_item(index, const item[]); = 2 params { // Check index. if (params[1] < 1 || params[1] > gpGlobals->maxClients) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid player %d", params[1]); return 0; } else if (!MF_IsPlayerIngame(params[1])) { MF_LogError(amx, AMX_ERR_NATIVE, "Player %d is not in game", params[1]); return 0; } // Get player pointer. edict_t *pPlayer = MF_GetPlayerEdict(params[1]); // Create item entity pointer edict_t *pItemEntity; // Make an "intstring" out of 2nd parameter int length; const char *szItem = MF_GetAmxString(amx, params[2], 1, &length); //check for valid item if (strncmp(szItem, "weapon_", 7) && strncmp(szItem, "ammo_", 5) && strncmp(szItem, "item_", 5) && strncmp(szItem, "tf_weapon_", 10) ) { return 0; } string_t item = ALLOC_STRING(szItem); // Using MAKE_STRING makes "item" contents get lost when we leave this scope! ALLOC_STRING seems to allocate properly... pItemEntity = CREATE_NAMED_ENTITY(item); if (FNullEnt(pItemEntity)) { MF_LogError(amx, AMX_ERR_NATIVE, "Item \"%s\" failed to create", szItem); return 0; } pItemEntity->v.origin = pPlayer->v.origin; pItemEntity->v.spawnflags |= (1 << 30); //SF_NORESPAWN; MDLL_Spawn(pItemEntity); int save = pItemEntity->v.solid; MDLL_Touch(pItemEntity, ENT(pPlayer)); if (pItemEntity->v.solid == save) { REMOVE_ENTITY(pItemEntity); //the function did not fail - we're just deleting the item return -1; } return ENTINDEX(pItemEntity); }
// native socket_send(_socket, _data[], _length); static cell AMX_NATIVE_CALL socket_send(AMX *amx, cell *params) /* 3 param */ { // We get the string from amx int len; int socket = params[1]; char* data = MF_GetAmxString(amx,params[2],0,&len); // And send it to the socket return send(socket, data, len, 0); }
//public QueryHandler(state, Handle:query, error[], errnum, data[], size) //native SQL_ThreadQuery(Handle:cn_tuple, const handler[], const query[], const data[]="", dataSize=0); static cell AMX_NATIVE_CALL SQL_ThreadQuery(AMX *amx, cell *params) { if (!g_pWorker) { MF_LogError(amx, AMX_ERR_NATIVE, "Thread worker was unable to start."); return 0; } SQL_Connection *cn = (SQL_Connection *)GetHandle(params[1], Handle_Connection); if (!cn) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid info tuple handle: %d", params[1]); return 0; } int len; const char *handler = MF_GetAmxString(amx, params[2], 0, &len); int fwd = MF_RegisterSPForwardByName(amx, handler, FP_CELL, FP_CELL, FP_STRING, FP_CELL, FP_ARRAY, FP_CELL, FP_DONE); if (fwd < 1) { MF_LogError(amx, AMX_ERR_NATIVE, "Function not found: %s", handler); return 0; } MysqlThread *kmThread; g_QueueLock->Lock(); if (g_FreeThreads.empty()) { kmThread = new MysqlThread(); } else { kmThread = g_FreeThreads.front(); g_FreeThreads.pop(); } g_QueueLock->Unlock(); kmThread->SetInfo(cn->db); kmThread->SetForward(fwd); kmThread->SetQuery(MF_GetAmxString(amx, params[3], 1, &len)); kmThread->SetCellData(MF_GetAmxAddr(amx, params[4]), (ucell)params[5]); g_pWorker->MakeThread(kmThread); return 1; }
// native geoip_continent_name(const ip[], result[], len, id = -1); static cell AMX_NATIVE_CALL amx_geoip_continent_name(AMX *amx, cell *params) { int length; char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length)); const char *path[] = { "continent", "names", getLang(params[4]), NULL }; const char *continent = lookupString(ip, path, &length); return MF_SetAmxStringUTF8Char(amx, params[2], continent ? continent : "", length, params[3]); }
// native geoip_longitude(const ip[]); static cell AMX_NATIVE_CALL amx_geoip_longitude(AMX *amx, cell *params) { int length; char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length)); const char *path[] = { "location", "longitude", NULL }; double longitude = lookupDouble(ip, path); return amx_ftoc(longitude); }