Jump to content

Nex-AC - Anticheat profesional (Instalare + Setare direct din joc)


Recommended Posts

Posted

Nex-AC (Anticheat) este unul dintre cele mai populare anticheat-uri din lumea SAMP-ului. Spre deosebire de alte soluții care necesită pluginuri complexe, Nex-AC rulează direct din script, fiind tradus în peste 20 de limbi (inclusiv română) și având protecții pentru mai bine de 40 de tipuri de hack-uri (FlyHack, SpeedHack, AirBreak, GodMode, MoneyHack etc.).

Pasul 1: descărcarea fișierelor

Pentru început, ai nevoie de fișierele oficiale Nex-AC. Descarcă pe GitHub "Nex-AC" (by NexiusTailer) și descarcă ultima versiune. Vei avea nevoie de:

  1. Fișierul nex-ac.inc (îl pui în folderul scriptului tău: pawno/include/).

  2. Folderul nex-ac (care conține fișierele de limbă, inclusiv romanian.lang). Acesta trebuie pus în folderul principal al serverului tău, în scriptfiles/.

Structura în scriptfiles ar trebui să arate așa: scriptfiles/nex-ac/romanian.lang

Pasul 2: integrarea în Gamemode (GM)

Nex-AC folosește o metodă numită "hooking". Ca să funcționeze corect și să nu dea erori de compilare, el trebuie adăugat la începutul scriptului, dar DUPĂ include-ul principal din SA-MP și după cele de MySQL/Streamer dacă le folosești.

Deschide gamemode-ul tău și adaugă:

#include <a_samp>
#include <a_mysql>
#include <streamer>

// ADĂUGĂ NEX-AC AICI (După include-urile de bază, dar înaintea scriptului tău)
#define AC_USE_BUILD_IN_BAN 1 // 1 = folosește sistemul de ban integrat în anticheat, 0 = folosești sistemul tău
#include <nex-ac>


Pasul 3: configurarea setărilor (OnCheatDetected)

Când Nex-AC prinde un codat, el nu îi dă direct kick/ban de la sine fără să te întrebe. El apelează un callback public numit OnCheatDetected. Aici decizi tu ce se întâmplă cu jucătorul (dacă primește Kick, Ban, sau doar alertă pe chat-ul adminilor).

Adaugă acest cod undeva în gamemode-ul tău (în afara altor funcții):

public OnCheatDetected(playerid, ip_address[], type, code, version, value)
{
    // Verificăm dacă jucătorul este admin. Adminii pot fi imuni la teste/false-uri.
    // Înlocuiește IsPlayerAdminEx cu funcția ta de admin creată în pașii anteriori!
    if(IsPlayerAdminEx(playerid)) return 1; 

    new string[256], pName[MAX_PLAYER_NAME];
    GetPlayerName(playerid, pName, sizeof(pName));

    // 'code' reprezintă ID-ul hack-ului detectat. 
    // Poți face acțiuni personalizate în funcție de gravitate.
    
    switch(code)
    {
        case 0, 1, 2, 3: // Exemple de coduri pentru FlyHack, AirBreak, SpeedHack
        {
            format(string, sizeof(string), "{FF0000}[Anticheat] {FFFFFF}Jucătorul %s[%d] a primit Ban pentru Hack (Cod: %d).", pName, playerid, code);
            SendClientMessageToAll(0xFF0000FF, string);
            
            // Îi dăm ban folosind funcția nativă din Nex-AC
            BanPlayer(playerid, "Nex-AC: Folosire de Cheat-uri"); 
        }
        default: // Pentru restul hack-urilor mai puțin grave sau potențiale erori (false-positives)
        {
            format(string, sizeof(string), "{FF0000}[Anticheat] {FFFFFF}Jucătorul %s[%d] a primit Kick pentru acțiuni suspecte (Cod: %d).", pName, playerid, code);
            SendClientMessageToAll(0xFF0000FF, string);
            
            KickPlayer(playerid); // Funcție nativă Nex-AC care rezolvă bug-ul de kick din SA-MP
        }
    }
    return 1;
}


Pasul 4: regula de Aur (Înlocuirea funcțiilor native)

Aceasta este cea mai importantă parte a tutorialului. Dacă serverul tău oferă bani, arme sau teleportează jucătorii prin comenzi/sisteme normale, Nex-AC va crede că jucătorul trișează (pentru că vede că jucătorul a primit bani "din senin") și îi va da kick.

Pentru a preveni acest lucru, Nex-AC înlocuiește funcțiile native din SA-MP cu versiuni modificate (anticheat-safe). Tu nu trebuie să schimbi nimic în codul tău, Nex-AC face asta automat prin macro-uri, DAR trebuie să fii atent la un detaliu:

Dacă în gamemode-ul tău folosești scripturi secundare (Filterscripts), funcțiile de resetare bani sau teleportare executate din filterscript-uri vor fi detectate ca hack de către gamemode-ul principal.

Recomandare: evită complet folosirea filterscript-urilor pentru acțiuni ce țin de bani, arme și poziție dacă folosești Nex-AC, sau adaugă #include <nex-ac> și în acele filterscript-uri.
 

Funcțiile pe care Nex-AC le monitorizează automat:

  • GivePlayerMoney / ResetPlayerMoney / GetPlayerMoney

  • GivePlayerWeapon / ResetPlayerWeapons

  • SetPlayerPos / SetVehiclePos

  • SetPlayerHealth / SetPlayerArmour

Atâta timp cât modifici banii sau poziția jucătorilor doar prin funcțiile standard de mai sus în GM-ul tău, Nex-AC va ști că este o acțiune legitimă și nu va pedepsi jucătorul.


Pasul 5: funcții utile din Nex-AC pe care le poți folosi

Nex-AC îți oferă câteva funcții noi (native) foarte utile pe care le poți apela în comenzile tale de admini:

  1. EnableAntiCheat(code, bool:enable)

    • Dezactivează sau activează un anumit modul de anticheat în timp real.

    • Exemplu: Dacă vrei să dezactivezi protecția de SpeedHack (cod 2) pe server: EnableAntiCheat(2, false);

  2. EnableAntiCheatForPlayer(playerid, code, bool:enable)

    • Oferă imunitate unui anumit jucător la un anumit cod. Util pentru teste de către admini.

  3. GetPlayerWeaponID(playerid, slot)

 

Returnează ID-ul armei dintr-un anumit slot, dar securizat prin baza de date Nex-AC, prevenind hack-urile care păcălesc GetPlayerWeapon.



Probleme frecvente

Jucătorii primesc kick când intră în Tuning Shop sau la Spawn, sistemele vechi de tuning sau spawn teleportează jucătorul rapid de câteva ori. Dacă pățești asta, caută ID-ul codului trimis pe chat și folosește EnableAntiCheat(cod, false); în OnGameModeInit pentru a opri acea protecție specifică care dă erori pe stilul tău de script.

Erori la compilare (Symbol already defined): Apare dacă ai pus #include <nex-ac> de două ori sau l-ai pus la sfârșitul scriptului în loc de început. Mută-l imediat sub #include <a_samp>.


GESTIONARE DIRECT DIN JOC
 

Structura Tabelului MySQL (SQL)

Rulează această comandă SQL în baza ta de date pentru a crea tabelul dedicat stărilor anticheat-ului:
 

CREATE TABLE IF NOT EXISTS `server_anticheat` (
  `module_id` int(11) NOT NULL,
  `module_name` varchar(32) NOT NULL,
  `is_enabled` tinyint(1) NOT NULL DEFAULT 1,
  PRIMARY KEY (`module_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 

Codul sursă Pawn actualizat cu MySQL R41

Adaugă acest cod în Gamemode-ul tău. Acesta va citi setările din baza de date la pornire și le va actualiza în timp real când le modifici din meniul /acpanel.
 

#include <a_samp>
#include <pawncmd>
#include <sscanf2>
#include <a_mysql>

// ---- Configurații Dialoguri ----
#define DIALOG_AC_MAIN      (8871)
#define DIALOG_AC_MODULES   (8872)
#define DIALOG_AC_IMMUNITY  (8873)

// Folosește handler-ul tău global de MySQL dacă ai deja unul (ex: SQL, handle, etc.)
extern MySQL:SQL_Handle; 

enum E_AC_MODULE_INFO {
    acCode,
    acName[32]
}

new const AC_Modules[][E_AC_MODULE_INFO] = {
    {0, "AirBreak (Pe jos)"},
    {1, "AirBreak (În vehicul)"},
    {2, "FlyHack (Pe jos)"},
    {3, "FlyHack (În vehicul)"},
    {4, "SpeedHack (Pe jos)"},
    {5, "SpeedHack (În vehicul)"},
    {11, "Teleport (Pe jos)"},
    {12, "Teleport (În vehicul)"},
    {16, "Weapon Hack (Arme)"},
    {17, "Infinite Ammo (Muniție)"},
    {18, "Money Hack (Bani)"},
    {22, "Health Hack (HP)"},
    {23, "Armour Hack (Armură)"},
    {24, "GodMode (Pe jos)"},
    {28, "CarJack Hack"},
    {32, "Rapid Fire (Trb. Rapid)"},
    {40, "Car Health Hack (Tuning)"}
};

// Forward-uri noi pentru MySQL
forward OnAnticheatSettingsLoad();

public OnGameModeInit()
{
    // Trimitem o interogare pentru a încărca starea modulelor salvate
    print("[MySQL] Se încarcă setările personalizate pentru Nex-AC...");
    mysql_tquery(SQL_Handle, "SELECT * FROM `server_anticheat`", "OnAnticheatSettingsLoad");
    return 1;
}

// ---- Încărcarea Setărilor din Baza de Date ----
public OnAnticheatSettingsLoad()
{
    new rows = cache_num_rows();
    
    // Dacă baza de date este goală (prima pornire a serverului), o populăm cu valorile implicite (toate pornite)
    if(rows == 0) 
    {
        print("[MySQL] Tabelul anticheat este gol. Se populează cu modulele implicite...");
        new query[256];
        for(new i = 0; i < sizeof(AC_Modules); i++) 
        {
            mysql_format(SQL_Handle, query, sizeof(query), 
                "INSERT INTO `server_anticheat` (`module_id`, `module_name`, `is_enabled`) VALUES ('%d', '%e', '1') ON DUPLICATE KEY UPDATE `is_enabled`='1'", 
                AC_Modules[i][acCode], AC_Modules[i][acName]
            );
            mysql_tquery(SQL_Handle, query);
            
            // Le lăsăm pornite nativ în Nex-AC
            EnableAntiCheat(AC_Modules[i][acCode], true);
        }
        return 1;
    }
    
    // Dacă există deja salvări în baza de date, le aplicăm pe server
    new m_id, is_enabled;
    for(new i = 0; i < rows; i++) 
    {
        cache_get_value_name_int(i, "module_id", m_id);
        cache_get_value_name_int(i, "is_enabled", is_enabled);
        
        // Aplicăm starea încărcată (0 = oprit, 1 = pornit) în Nex-AC
        EnableAntiCheat(m_id, (is_enabled == 1) ? true : false);
    }
    printf("[MySQL] S-au aplicat cu succes %d setări de module pentru Nex-AC.", rows);
    return 1;
}

// ---- Funcție ajutătoare pentru salvare rapidă ----
stock SaveAnticheatModuleStatus(module_id, bool:status)
{
    new query[128];
    mysql_format(SQL_Handle, query, sizeof(query), 
        "UPDATE `server_anticheat` SET `is_enabled` = '%d' WHERE `module_id` = '%d'", 
        (status == true) ? 1 : 0, module_id
    );
    mysql_tquery(SQL_Handle, query);
}

// ---- Comanda de Admin ----
cmd:acpanel(playerid, params[])
{
    if(!IsPlayerAdminEx(playerid)) return SendClientMessage(playerid, 0xFF0000FF, "Nu ai permisiunea de a folosi această comandă.");
    
    ShowPlayerDialog(playerid, DIALOG_AC_MAIN, DIALOG_STYLE_LIST, 
        "{FF0000}Nex-AC {FFFFFF}- Panou MySQL Profesional", 
        "1. Gestionare Module Anticheat (Salvare Persistentă)\n2. Oferă Imunitate unui Jucător (Până la relog)\n3. Stare Anticheat (Sumar)", 
        "Selectează", "Închide"
    );
    return 1;
}
alias:acpanel("ac");

// ---- Răspunsurile Dialogurilor ----
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    if(dialogid == DIALOG_AC_MAIN)
    {
        if(!response) return 1;
        
        switch(listitem)
        {
            case 0: // Afișare module
            {
                new dialogStr[1024], lineStr[128];
                format(dialogStr, sizeof(dialogStr), "Modul Anticheat\tStare Curentă (MySQL)\n");
                
                for(new i = 0; i < sizeof(AC_Modules); i++) {
                    new bool:status = bool:GetAntiCheatStatus(AC_Modules[i][acCode]); 
                    
                    format(lineStr, sizeof(lineStr), "%s\t%s\n", 
                        AC_Modules[i][acName], 
                        status ? "{00FF00}ACTIVAT" : "{FF0000}DEZACTIVAT"
                    );
                    strcat(dialogStr, lineStr);
                }
                
                ShowPlayerDialog(playerid, DIALOG_AC_MODULES, DIALOG_STYLE_TABLIST_HEADERS, 
                    "{FF0000}Nex-AC {FFFFFF}- Configurare Persistentă", dialogStr, "Comută", "Înapoi"
                );
            }
            case 1: // Imunitate temporară jucător
            {
                ShowPlayerDialog(playerid, DIALOG_AC_IMMUNITY, DIALOG_STYLE_INPUT, 
                    "{FF0000}Nex-AC {FFFFFF}- Imunitate Jucător", 
                    "Introdu ID-ul sau numele jucătorului:", 
                    "Oferă", "Înapoi"
                );
            }
            case 2: // Status
            {
                new statsStr[256];
                format(statsStr, sizeof(statsStr), 
                    "{FFFFFF}Versiune Nex-AC: {FFFF00}%s\n{FFFFFF}Stocare: {00FF00}Bază de date MySQL{FFFFFF}\n{FFFFFF}Module înregistrate: {FFFF00}%d", 
                    AC_VERSION, sizeof(AC_Modules)
                );
                ShowPlayerDialog(playerid, 9999, DIALOG_STYLE_MSGBOX, "{FF0000}Nex-AC {FFFFFF}- Status", statsStr, "Ok", "");
            }
        }
        return 1;
    }
    
    if(dialogid == DIALOG_AC_MODULES)
    {
        if(!response) return PC_ExecuteCommand(playerid, "/acpanel"); 
        
        new code = AC_Modules[listitem][acCode];
        new bool:newStatus = !bool:GetAntiCheatStatus(code); // Inversăm starea actuală
        
        // 1. Schimbăm starea în mod activ în memoria serverului
        EnableAntiCheat(code, newStatus);
        
        // 2. Trimitem modificarea direct în baza de date MySQL (Salvare persistentă)
        SaveAnticheatModuleStatus(code, newStatus);
        
        // Notificare admini
        new logStr[128], adminName[MAX_PLAYER_NAME];
        GetPlayerName(playerid, adminName, sizeof(adminName));
        format(logStr, sizeof(logStr), "{FF0000}[Anticheat] %s a %s modulul '%s' (Salvat în DB).", 
            adminName, newStatus ? "{00FF00}ACTIVAT" : "{FF0000}DEZACTIVAT", AC_Modules[listitem][acName]
        );
        
        for(new i = 0; i < MAX_PLAYERS; i++) {
            if(IsPlayerConnected(i) && IsPlayerAdminEx(i)) SendClientMessage(i, 0x33CCFFFF, logStr);
        }
        
        // Redeschidem meniul actualizat
        PC_ExecuteCommand(playerid, "/acpanel");
        return 1;
    }
    
    if(dialogid == DIALOG_AC_IMMUNITY)
    {
        if(!response) return PC_ExecuteCommand(playerid, "/acpanel");
        
        new targetid;
        if(sscanf(inputtext, "u", targetid) || !IsPlayerConnected(targetid)) {
            SendClientMessage(playerid, 0xFF0000FF, "Eroare: Jucător offline sau invalid.");
            return PC_ExecuteCommand(playerid, "/acpanel");
        }
        
        for(new i = 0; i < sizeof(AC_Modules); i++) {
            EnableAntiCheatForPlayer(targetid, AC_Modules[i][acCode], false);
        }
        
        new tName[MAX_PLAYER_NAME], msg[128];
        GetPlayerName(targetid, tName, sizeof(tName));
        format(msg, sizeof(msg), "{00FF00}[Anticheat] I-ai oferit imunitate temporară lui %s[%d].", tName, targetid);
        SendClientMessage(playerid, 0x00FF00FF, msg);
        return 1;
    }
    return 0;
}
 
  • Upvote 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more details you can also review our Terms of Use and Privacy Policy.