khain.dev Posted June 7 Posted June 7 Dependențe necesare: Pawn.CMD MySQL R-41 sscanf2 Structura tabelului MySQL (SQL) CREATE TABLE IF NOT EXISTS `server_reports` ( `id` int(11) NOT NULL AUTO_INCREMENT, `sender_name` varchar(24) NOT NULL, `reason` varchar(128) NOT NULL, `date_added` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Codul sursă pawn #include <a_samp> #include <pawncmd> #include <sscanf2> #include <a_mysql> // Include pluginul MySQL R41+ // ---- Configurații ---- #define MAX_REPORTS (50) #define DIALOG_REPORT_MAIN (9981) #define DIALOG_REPORT_TEXT (9982) #define DIALOG_REP_LIST (9983) #define REASON_LENGTH (128) #define COLOR_RED 0xFF0000FF #define COLOR_GREEN 0x00FF00FF #define COLOR_YELLOW 0xFFFF00FF #define COLOR_WHITE 0xFFFFFFFF #define COLOR_LIGHTBLUE 0x33CCFFFF // Înlocuiește "MySQL_Handle" cu variabila ta de conexiune MySQL dacă ai una existentă în GM new MySQL:SQL_Handle; // ---- Structuri de date ---- enum E_REPORT_DATA { repDatabaseID, // ID-ul unic din baza de date (MySQL Auto_Increment) repSenderID, // ID-ul jucătorului pe server (-1 dacă e offline dar raportul e încă în coadă) repSenderName[MAX_PLAYER_NAME], // Numele jucătorului (salvat pentru când e offline) repReason[REASON_LENGTH], bool:repActive } new ReportQueue[MAX_REPORTS][E_REPORT_DATA]; new TotalReports = 0; new bool:HasActiveReport[MAX_PLAYERS]; new PlayerUnderReport[MAX_PLAYERS]; // ---- Verificare Admin ---- stock IsPlayerAdminEx(playerid) { if(IsPlayerAdmin(playerid)) return 1; // Înlocuiește linia de mai jos cu variabila ta de admin (ex: if(PlayerInfo[playerid][pAdmin] >= 1) return 1;) return 0; } // ---- Forward-uri pentru MySQL ---- forward OnUnansweredReportsLoad(); forward OnReportInserted(queue_index, playerid); public OnGameModeInit() { // Inițializare coadă golită pe server for(new i = 0; i < MAX_REPORTS; i++) { ResetReportSlot(i); } // ATENȚIE: Dacă ai deja logica de conectare MySQL în GM, șterge liniile mysql_connect de mai jos! SQL_Handle = mysql_connect("127.0.0.1", "root", "", "server_db"); if(mysql_errno(SQL_Handle) != 0) { printf("[MySQL] Conexiunea a eșuat în sistemul de reporturi."); } else { printf("[MySQL] Conexiune reușită. Încărcăm rapoartele nerezolvate..."); // Încărcăm rapoartele nerezolvate salvate în baza de date mysql_tquery(SQL_Handle, "SELECT * FROM `server_reports` ORDER BY `id` ASC LIMIT 50", "OnUnansweredReportsLoad"); } return 1; } public OnPlayerConnect(playerid) { HasActiveReport[playerid] = false; PlayerUnderReport[playerid] = INVALID_PLAYER_ID; // Verificăm dacă jucătorul care s-a conectat are un raport rămas în coadă din sesiunea trecută new pName[MAX_PLAYER_NAME]; GetPlayerName(playerid, pName, sizeof(pName)); for(new i = 0; i < MAX_REPORTS; i++) { if(ReportQueue[i][repActive] && !strcmp(ReportQueue[i][repSenderName], pName, true)) { ReportQueue[i][repSenderID] = playerid; // Îi reasociem ID-ul curent de server HasActiveReport[playerid] = true; new str[128]; format(str, sizeof(str), "{FFFFFF}[REPORT] Raportul tău din sesiunea anterioară este încă în coadă pe poziția {FFFF00}%d{FFFFFF}.", i + 1); SendClientMessage(playerid, COLOR_GREEN, str); break; } } return 1; } public OnPlayerDisconnect(playerid, reason) { // Când un jucător iese, NU mai ștergem raportul din baza de date și nici din coadă! // Doar marcăm ID-ul ca invalid pe server, dar adminii îl vor vedea în continuare în listă după nume. if(HasActiveReport[playerid]) { for(new i = 0; i < MAX_REPORTS; i++) { if(ReportQueue[i][repActive] && ReportQueue[i][repSenderID] == playerid) { ReportQueue[i][repSenderID] = INVALID_PLAYER_ID; break; } } } if(PlayerUnderReport[playerid] != INVALID_PLAYER_ID) { new target = PlayerUnderReport[playerid]; if(IsPlayerConnected(target)) { SendClientMessage(target, COLOR_RED, "Adminul care iți procesa raportul s-a deconectat."); } PlayerUnderReport[playerid] = INVALID_PLAYER_ID; } return 1; } // ---- Funcții Ajutătoare (Helperi) ---- stock ResetReportSlot(i) { ReportQueue[i][repDatabaseID] = 0; ReportQueue[i][repSenderID] = INVALID_PLAYER_ID; ReportQueue[i][repSenderName][0] = '\0'; ReportQueue[i][repReason][0] = '\0'; ReportQueue[i][repActive] = false; } stock MessageToAdmins(color, const message[]) { for(new i = 0; i < MAX_PLAYERS; i++) { if(IsPlayerConnected(i) && IsPlayerAdminEx(i)) { SendClientMessage(i, color, message); } } } // ---- Logica MySQL R41 ---- public OnUnansweredReportsLoad() { new rows = cache_num_rows(); if(rows == 0) return printf("[MySQL] Nu s-au găsit rapoarte nerezolvate în baza de date."); TotalReports = 0; for(new i = 0; i < rows && i < MAX_REPORTS; i++) { ReportQueue[i][repActive] = true; cache_get_value_name_int(i, "id", ReportQueue[i][repDatabaseID]); cache_get_value_name(i, "sender_name", ReportQueue[i][repSenderName], MAX_PLAYER_NAME); cache_get_value_name(i, "reason", ReportQueue[i][repReason], REASON_LENGTH); ReportQueue[i][repSenderID] = INVALID_PLAYER_ID; // Va deveni valid dacă jucătorul se conectează TotalReports++; } printf("[MySQL] S-au încărcat cu succes %d rapoarte nerezolvate în coadă.", TotalReports); return 1; } stock SendReportToQueue(playerid, const reason[]) { if(TotalReports >= MAX_REPORTS) { return SendClientMessage(playerid, COLOR_RED, "Coada de rapoarte este plină! Încearcă din nou mai târziu."); } // Găsim primul slot liber local pe server for(new i = 0; i < MAX_REPORTS; i++) { if(!ReportQueue[i][repActive]) { ReportQueue[i][repActive] = true; ReportQueue[i][repSenderID] = playerid; GetPlayerName(playerid, ReportQueue[i][repSenderName], MAX_PLAYER_NAME); format(ReportQueue[i][repReason], REASON_LENGTH, "%s", reason); TotalReports++; HasActiveReport[playerid] = true; // Salvare threaded în MySQL R41 new query[256]; mysql_format(SQL_Handle, query, sizeof(query), "INSERT INTO `server_reports` (`sender_name`, `reason`) VALUES ('%e', '%e')", ReportQueue[i][repSenderName], reason); mysql_tquery(SQL_Handle, query, "OnReportInserted", "dd", i, playerid); return 1; } } return 0; } public OnReportInserted(queue_index, playerid) { // Salvăm ID-ul generat de baza de date (Primary Key) direct în slotul aferent din coadă ReportQueue[queue_index][repDatabaseID] = mysql_insert_id(SQL_Handle); if(IsPlayerConnected(playerid)) { new str[128]; format(str, sizeof(str), "{FFFFFF}[REPORT] Raportul tău a fost salvat! Poziția în coadă: {FFFF00}%d{FFFFFF}.", TotalReports); SendClientMessage(playerid, COLOR_GREEN, str); new name[MAX_PLAYER_NAME]; GetPlayerName(playerid, name, sizeof(name)); format(str, sizeof(str), "{33CCFF}[Report nou] (%d) %s[%d]: %s", TotalReports, name, playerid, ReportQueue[queue_index][repReason]); MessageToAdmins(COLOR_LIGHTBLUE, str); } return 1; } stock DeleteReportFromDatabase(db_id) { if(db_id == 0) return 0; new query[128]; mysql_format(SQL_Handle, query, sizeof(query), "DELETE FROM `server_reports` WHERE `id` = '%d'", db_id); mysql_tquery(SQL_Handle, query); return 1; } stock RemoveReportFromQueue(queue_index) { if(!ReportQueue[queue_index][repActive]) return 0; // Ștergem din baza de date DeleteReportFromDatabase(ReportQueue[queue_index][repDatabaseID]); // Resetăm variabila per jucător dacă este online new target = ReportQueue[queue_index][repSenderID]; if(target != INVALID_PLAYER_ID && IsPlayerConnected(target)) { HasActiveReport[target] = false; } // Resetăm slotul și rearanjăm coada (FIFO) ResetReportSlot(queue_index); TotalReports--; ReorderQueue(); return 1; } stock ReorderQueue() { new tempQueue[MAX_REPORTS][E_REPORT_DATA]; new count = 0; for(new i = 0; i < MAX_REPORTS; i++) { if(ReportQueue[i][repActive]) { tempQueue[count] = ReportQueue[i]; count++; } } for(new i = 0; i < MAX_REPORTS; i++) { if(i < count) { ReportQueue[i] = tempQueue[i]; } else { ResetReportSlot(i); } } TotalReports = count; } // ---- Comenzi Jucători (Pawn.CMD) ---- cmd:report(playerid, params[]) { if(HasActiveReport[playerid]) { return SendClientMessage(playerid, COLOR_RED, "Eroare: Ai deja un raport activ în coadă. Te rugăm să aștepți."); } ShowPlayerDialog(playerid, DIALOG_REPORT_MAIN, DIALOG_STYLE_LIST, "{FFFFFF}Sistem de Raportare", "1. Raportează un Codat / Hacker\n2. Raportează limbaj / jigniri\n3. Am blocat / Am nevoie de ajutor (Unstuck)\n4. Altă problemă (Scrie text manual)", "Selectează", "Închide" ); return 1; } alias:report("rep"); // ---- Comenzi Administratori (Pawn.CMD) ---- cmd:ar(playerid, params[]) { if(!IsPlayerAdminEx(playerid)) return SendClientMessage(playerid, COLOR_RED, "Nu ai permisiunea de a folosi această comandă."); if(PlayerUnderReport[playerid] != INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_RED, "Eroare: Procesezi deja un raport! Folosește /cr pentru a-l închide."); if(TotalReports == 0) return SendClientMessage(playerid, COLOR_RED, "Nu există rapoarte active în coadă în acest moment."); new queueIndex = 0; new inputIndex; if(!sscanf(params, "d", inputIndex)) { inputIndex = inputIndex - 1; if(inputIndex >= 0 && inputIndex < TotalReports && ReportQueue[inputIndex][repActive]) { queueIndex = inputIndex; } else { return SendClientMessage(playerid, COLOR_RED, "Poziție invalidă în coadă. Folosește /reports pentru listă."); } } new targetid = ReportQueue[queueIndex][repSenderID]; new reason[REASON_LENGTH]; format(reason, sizeof(reason), "%s", ReportQueue[queueIndex][repReason]); new adminName[MAX_PLAYER_NAME], str[256]; GetPlayerName(playerid, adminName, sizeof(adminName)); // Verificăm dacă jucătorul mai este pe server if(targetid == INVALID_PLAYER_ID || !IsPlayerConnected(targetid)) { format(str, sizeof(str), "{FFFFFF}Ai preluat raportul lui {FFFF00}%s{FFFFFF} (offline). Motiv: %s.", ReportQueue[queueIndex][repSenderName], reason); SendClientMessage(playerid, COLOR_GREEN, str); format(str, sizeof(str), "{33CCFF}[Admin] %s a eliminat raportul de la offline al lui %s. Motiv: %s", adminName, ReportQueue[queueIndex][repSenderName], reason); MessageToAdmins(COLOR_LIGHTBLUE, str); // Din moment ce este offline, doar curățăm raportul din listă/bază de date direct RemoveReportFromQueue(queueIndex); return 1; } // Jucătorul este online, începem conversația asistată PlayerUnderReport[playerid] = targetid; format(str, sizeof(str), "{FFFFFF}[REPORT] Adminul {FFFF00}%s{FFFFFF} ți-a acceptat raportul. Acesta va discuta cu tine acum.", adminName); SendClientMessage(targetid, COLOR_GREEN, str); format(str, sizeof(str), "{33CCFF}[Admin] %s a preluat raportul lui %s[%d]. Motiv: %s", adminName, ReportQueue[queueIndex][repSenderName], targetid, reason); MessageToAdmins(COLOR_LIGHTBLUE, str); format(str, sizeof(str), "{FFFFFF}Ai preluat raportul lui %s. Motiv: %s. Folosește /cr când ai terminat.", ReportQueue[queueIndex][repSenderName], reason); SendClientMessage(playerid, COLOR_GREEN, str); // Îl eliminăm din MySQL și din coada de așteptare deoarece un admin se ocupă acum de el RemoveReportFromQueue(queueIndex); return 1; } cmd:cr(playerid, params[]) { if(!IsPlayerAdminEx(playerid)) return SendClientMessage(playerid, COLOR_RED, "Nu ai permisiunea de a folosi această comandă."); if(PlayerUnderReport[playerid] == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_RED, "Nu ai niciun raport activ în desfășurare."); new targetid = PlayerUnderReport[playerid]; new adminName[MAX_PLAYER_NAME], userName[MAX_PLAYER_NAME], str[128]; GetPlayerName(playerid, adminName, sizeof(adminName)); if(IsPlayerConnected(targetid)) { GetPlayerName(targetid, userName, sizeof(userName)); format(str, sizeof(str), "{FFFFFF}[REPORT] Adminul {FFFF00}%s{FFFFFF} ți-a închis raportul. Sperăm că te-am ajutat!", adminName); SendClientMessage(targetid, COLOR_YELLOW, str); format(str, sizeof(str), "{FFFFFF}Ai închis cu succes raportul lui %s.", userName); SendClientMessage(playerid, COLOR_GREEN, str); } else { SendClientMessage(playerid, COLOR_GREEN, "Ai închis raportul curent (jucătorul era deconectat)."); } PlayerUnderReport[playerid] = INVALID_PLAYER_ID; return 1; } cmd:reports(playerid, params[]) { if(!IsPlayerAdminEx(playerid)) return SendClientMessage(playerid, COLOR_RED, "Nu ai permisiunea de a folosi această comandă."); if(TotalReports == 0) return SendClientMessage(playerid, COLOR_RED, "Nu există rapoarte active în coadă."); new dialogStr[1024], lineStr[150]; format(dialogStr, sizeof(dialogStr), "Poziție\tJucător\tStare\tMotiv\n"); for(new i = 0; i < MAX_REPORTS; i++) { if(ReportQueue[i][repActive]) { if(ReportQueue[i][repSenderID] != INVALID_PLAYER_ID && IsPlayerConnected(ReportQueue[i][repSenderID])) { format(lineStr, sizeof(lineStr), "#%d\t%s (%d)\t{00FF00}Online{FFFFFF}\t%s\n", i+1, ReportQueue[i][repSenderName], ReportQueue[i][repSenderID], ReportQueue[i][repReason]); } else { format(lineStr, sizeof(lineStr), "#%d\t%s\t{FF0000}Offline{FFFFFF}\t%s\n", i+1, ReportQueue[i][repSenderName], ReportQueue[i][repReason]); } strcat(dialogStr, lineStr); } } ShowPlayerDialog(playerid, DIALOG_REP_LIST, DIALOG_STYLE_TABLIST_HEADERS, "{FFFFFF}Listă Coadă Rapoarte (MySQL)", dialogStr, "Acceptă primul", "Închide"); return 1; } // ---- Dialoguri ---- public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) { if(dialogid == DIALOG_REPORT_MAIN) { if(!response) return 1; switch(listitem) { case 0: SendReportToQueue(playerid, "Posibil codat / hacker (necesită spectate)"); case 1: SendReportToQueue(playerid, "Limbaj vulgar / Jigniri / Spam"); case 2: SendReportToQueue(playerid, "Am rămas blocat (solicit unstuck / flip)"); case 3: { ShowPlayerDialog(playerid, DIALOG_REPORT_TEXT, DIALOG_STYLE_INPUT, "{FFFFFF}Raport - Detalii manuale", "Te rugăm să descrii problema ta cât mai detaliat posibil în căsuța de mai jos:", "Trimite", "Înapoi" ); } } return 1; } if(dialogid == DIALOG_REPORT_TEXT) { if(!response) return PC_ExecuteCommand(playerid, "/report"); if(strlen(inputtext) < 5 || strlen(inputtext) > 120) { SendClientMessage(playerid, COLOR_RED, "Eroare: Textul raportului trebuie să aibă între 5 și 120 de caractere."); return PC_ExecuteCommand(playerid, "/report"); } SendReportToQueue(playerid, inputtext); return 1; } if(dialogid == DIALOG_REP_LIST) { if(response) { PC_ExecuteCommand(playerid, "/ar"); } return 1; } return 0; } 1
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now