diff --git a/.github/workflow/build.yml b/.github/workflow/build.yml new file mode 100644 index 0000000..0387d10 --- /dev/null +++ b/.github/workflow/build.yml @@ -0,0 +1,50 @@ +name: Build + +on: [push, pull_request, workflow_dispatch] + +jobs: + compile: + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.sm-version == '1.11.x' }} + strategy: + matrix: + sm-version: [ '1.9.x', '1.10.x', '1.11.x' ] + # compiler-options: [ '', '__MADEBUG=1' ] + + env: + DEBUG: ${{ contains(matrix.compiler-options, '__XDEBUG=1') }} + + name: "Build SM ${{ matrix.sm-version }} ${{ matrix.compiler-options != '' && format('({0})', matrix.compiler-options) || '' }}" + steps: + - uses: actions/checkout@v2 + + - name: Setup SP + uses: rumblefrog/setup-sp@master + with: + version: ${{ matrix.sm-version }} + + - name: Run compiler + run: | + cd addons/sourcemod + mkdir plugins + cd scripting + spcomp VIP_Core.sp -E -o ../plugins/VIP_Core.smx -iinclude ${{ matrix.compiler-options }} + + # - name: Make artifact archive + # if: github.ref == 'refs/heads/master' + # run: | + # if [[ "$DEBUG" == "true" ]]; then export CUSTOM_POSTFIX="d"; fi + # SMVERSION_FULL=${{ matrix.sm-version }} + + # export SMVERSION_SHORT=${SMVERSION_FULL:0:-2} + # export ARCHIVE_FILENAME=sbma-newplugin.${GITHUB_SHA::7}.${SMVERSION_SHORT}${CUSTOM_POSTFIX}.tar.gz + + # echo "ARCHIVE_FILENAME=$ARCHIVE_FILENAME" >> $GITHUB_ENV + # echo "SMVERSION_SHORT=$SMVERSION_SHORT" >> $GITHUB_ENV + + # tar -cvf $ARCHIVE_FILENAME addons + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: VIP-Core + path: ../VIP-Core diff --git a/.gitignore b/.gitignore index 81cca17..b6f6890 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode/ *.smx +*.code-workspace diff --git a/.travis.yml b/.travis.yml index e07092a..fcaefd0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,4 +56,4 @@ deploy: #Notifications notifications: - email: false + email: true diff --git a/addons/sourcemod/scripting/VIP_Core.sp b/addons/sourcemod/scripting/VIP_Core.sp index 55da388..5efd83e 100644 --- a/addons/sourcemod/scripting/VIP_Core.sp +++ b/addons/sourcemod/scripting/VIP_Core.sp @@ -4,24 +4,35 @@ #include #include -#include #if !defined VIP_CORE_VERSION +#if defined COMMIT_HASH +#define VIP_CORE_VERSION "3.1.0 DEV (#" ... COMMIT_HASH ... ")" +#else #define VIP_CORE_VERSION "3.1.0 DEV" #endif +#endif -#define DEBUG_MODE 0 // Режим отладки +#define DEBUG_MODE 0 // Режим отладки -#define USE_ADMINMENU 1 // Включение админ-меню для управления VIP +#define USE_ADMINMENU 1 // Включение админ-меню для управления VIP #define USE_MORE_SERVERS 1 // Включить/Отключить режим при котором если ID сервера у игрока 0 - то VIP будет работать на всех серверах + +#define USE_CLIENTPREFS 0 // Использовать ли стандартные куки для хранения данных игроков + #define CHARSET "utf8mb4" #define COLLATION "utf8mb4_unicode_ci" //#define CHARSET "utf8" //#define COLLATION "utf8_unicode_ci" + +#if USE_CLIENTPREFS 1 +#include +#endif + #if USE_ADMINMENU 1 #undef REQUIRE_PLUGIN #include @@ -41,6 +52,7 @@ public Plugin myinfo = #include "vip/Downloads.sp" #include "vip/Colors.sp" #include "vip/UTIL.sp" +#include "vip/Storage.sp" #include "vip/Features.sp" #include "vip/Sounds.sp" #include "vip/Info.sp" @@ -88,6 +100,7 @@ public void OnPluginStart() g_bIsTranslationPhraseExistsAvailable = (CanTestFeatures() && GetFeatureStatus(FeatureType_Native, "TranslationPhraseExists") == FeatureStatus_Available); + API_SetupForwards(); ReadConfigs(); VIPMenu_Setup(); @@ -96,7 +109,6 @@ public void OnPluginStart() #endif Cvars_Setup(); - API_SetupForwards(); HookEvent("player_spawn", Event_PlayerSpawn); HookEvent("player_death", Event_PlayerDeath); @@ -110,10 +122,10 @@ public void OnPluginStart() #if USE_ADMINMENU 1 RegConsoleCmd("sm_vipadmin", VIPAdmin_CMD); - if(LibraryExists("adminmenu")) + if (LibraryExists("adminmenu")) { TopMenu hTopMenu = GetAdminTopMenu(); - if(hTopMenu != null) + if (hTopMenu != null) { OnAdminMenuReady(hTopMenu); } @@ -129,11 +141,11 @@ public void OnAllPluginsLoaded() #if USE_ADMINMENU 1 public Action OnClientSayCommand(int iClient, const char[] szCommand, const char[] szArgs) { - if(iClient > 0 && iClient <= MaxClients && szArgs[0]) + if (iClient > 0 && iClient <= MaxClients && szArgs[0]) { - if(g_iClientInfo[iClient] & IS_WAIT_CHAT_SEARCH) + if (g_iClientInfo[iClient] & IS_WAIT_CHAT_SEARCH) { - if(g_iClientInfo[iClient] & IS_WAIT_CHAT_SEARCH) + if (g_iClientInfo[iClient] & IS_WAIT_CHAT_SEARCH) { ShowWaitSearchMenu(iClient, szArgs); } @@ -145,3 +157,20 @@ public Action OnClientSayCommand(int iClient, const char[] szCommand, const char return Plugin_Continue; } #endif + +public void OnMapStart() +{ + LoadSounds(); + ReadDownloads(); +} + +public void OnConfigsExecuted() +{ + DebugMessage("OnConfigsExecuted: %x", g_hDatabase) + CMD_Register(); + + if (g_hDatabase && (GLOBAL_INFO & IS_STARTED)) + { + RemoveExpAndOutPlayers(); + } +} diff --git a/addons/sourcemod/scripting/include/vip_core.inc b/addons/sourcemod/scripting/include/vip_core.inc index c85cb6d..d0b2e8b 100644 --- a/addons/sourcemod/scripting/include/vip_core.inc +++ b/addons/sourcemod/scripting/include/vip_core.inc @@ -115,6 +115,15 @@ forward void VIP_OnPlayerSpawn(int iClient, int iTeam, bool bIsVIP); */ forward Action VIP_OnShowClientInfo(int iClient, const char[] szEvent, const char[] szType, KeyValues hKeyValues); +/** + * Вызывается когда загружены данные из хранилища игрока + * + * @param iClient Индекс игрока. + * + * @noreturn +*/ +forward void VIP_OnClientStorageLoaded(int iClient); + /** * Вызывается когда у VIP-игрока изменяется статус функции. * @@ -138,6 +147,15 @@ forward Action VIP_OnFeatureToggle(int iClient, const char[] szFeature, VIP_Togg */ forward void VIP_OnVIPLoaded(); +/** + * Вызывается когда VIP-плагин загрузил настройки. + * + * @noparams + * + * @noreturn +*/ +forward void VIP_OnConfigsLoaded(); + /** * Вызывается когда VIP-функция была зарегистрирована. * @@ -271,7 +289,7 @@ native int VIP_GetClientAccessTime(int iClient); native bool VIP_SetClientAccessTime(int iClient, int iTime, bool bInDB = true); /** - * Получает VIP-группу игрока. + * Получает группу игрока. * * @param iClient Индекс игрока. * @param szGroup Буфер, в который будет помещен результат. @@ -283,10 +301,10 @@ native bool VIP_SetClientAccessTime(int iClient, int iTime, bool bInDB = true); native bool VIP_GetClientVIPGroup(int iClient, char[] szGroup, int iMaxLength); /** - * Устанавливает игроку VIP-группу. + * Устанавливает игроку группу. * * @param iClient Индекс игрока. - * @param szGroup VIP-группа. + * @param szGroup группа. * @param bInDBB Изменять ли в базе данных. * * @return true - Успешно. @@ -304,15 +322,39 @@ native bool VIP_SetClientVIPGroup(int iClient, const char[] szGroup, bool bInDB native StringMap VIP_GetVIPClientTrie(int iClient); /** - * Проверяет наличие VIP-группы. + * Проверяет наличие группы. * - * @param szGroup Имя VIP-группы. + * @param szGroup Имя группы. * - * @return true - VIP-группа существует. - * false - VIP-группа не существует. + * @return true - группа существует. + * false - группа не существует. */ +native bool VIP_IsGroupExists(const char[] szGroup); + +#pragma deprecated Use VIP_IsGroupExists() instead native bool VIP_IsValidVIPGroup(const char[] szGroup); +/** + * Добавляет группу. + * + * @param szGroup Имя группы. + * @param hFeatures Параметры группы. + * + * @return true - успешно. + * false - ошибка. +*/ +native bool VIP_AddGroup(const char[] szGroup, KeyValues hFeatures); + +/** + * Удаляет группу. + * + * @param szGroup Имя группы. + * + * @return true - успешно. + * false - ошибка. +*/ +native bool VIP_RemoveGroup(const char[] szGroup); + /** * Выводит игроку сообщение в чат с приставкой (фраза в переводе "VIP_CHAT_PREFIX"). * @@ -362,7 +404,7 @@ native void VIP_SendClientVIPMenu(int iClient, bool bSelection = false); * @param iAdmin Индекс админа (0 - сервер, -1 - плагин). * @param iClient Индекс игрока. * @param iTime Время в секундах. - * @param szGroup Имя VIP-группы. + * @param szGroup Имя группы. * @param bAddToDB Добавлять ли в базу данных. * * @noreturn @@ -449,7 +491,7 @@ native void VIP_UnregisterMe(); * @param szFeature Уникальное имя ф-и. * * @return true - VIP-функция существует. - * false - VIP-функция не существует. + * false - VIP-функция не существует. */ native bool VIP_IsValidFeature(const char[] szFeature); @@ -580,6 +622,29 @@ native bool VIP_GiveClientFeature(int iClient, const char[] szFeature, const cha */ native bool VIP_RemoveClientFeature(int iClient, const char[] szFeature); + +/** + * Сохраняет значение в хранилище игрока + * + * @param iClient Индекс игрока. + * @param szKey Ключ + * @param szValue Значение + * + * @noreturn +*/ +native void VIP_SetClientStorageValue(int iClient, const char[] szKey, const char[] szValue); + +/** + * Получает значение из хранилища игрока + * + * @param szKey Ключ + * @param szValue Буфер, в который будет помещен результат. + * @param iMaxLength Размер буфера. + * + * @noreturn +*/ +native void VIP_GetClientStorageValue(int iClient, const char[] szKey, char[] szValue, int iMaxLength); + /** * Получает Handle базы данных. После работы необходимо закрыть с помощью CloseHandle() или delete * @@ -700,6 +765,9 @@ public void __pl_vip_core_SetNTVOptional() MarkNativeAsOptional("VIP_GetVIPClientTrie"); MarkNativeAsOptional("VIP_SendClientVIPMenu"); MarkNativeAsOptional("VIP_IsValidVIPGroup"); + MarkNativeAsOptional("VIP_IsGroupExists"); + MarkNativeAsOptional("VIP_AddGroup"); + MarkNativeAsOptional("VIP_RemoveGroup"); MarkNativeAsOptional("VIP_GetClientFeatureStatus"); MarkNativeAsOptional("VIP_SetClientFeatureStatus"); MarkNativeAsOptional("VIP_IsClientFeatureUse"); @@ -717,5 +785,7 @@ public void __pl_vip_core_SetNTVOptional() MarkNativeAsOptional("VIP_GiveClientVIP"); MarkNativeAsOptional("VIP_GiveClientFeature"); MarkNativeAsOptional("VIP_RemoveClientFeature"); + MarkNativeAsOptional("VIP_SetClientStorageValue"); + MarkNativeAsOptional("VIP_GetClientStorageValue"); } #endif diff --git a/addons/sourcemod/scripting/vip/API.sp b/addons/sourcemod/scripting/vip/API.sp index 506acab..5d21a6f 100644 --- a/addons/sourcemod/scripting/vip/API.sp +++ b/addons/sourcemod/scripting/vip/API.sp @@ -1,3 +1,5 @@ +#define VIP_CLIENT(%0) (g_hFeatures[%0] && IS_CLIENT_VIP(%0) && IS_CLIENT_LOADED(%0)) + static Handle g_hGlobalForward_OnVIPLoaded; static Handle g_hGlobalForward_OnClientPreLoad; static Handle g_hGlobalForward_OnClientLoaded; @@ -10,6 +12,8 @@ static Handle g_hGlobalForward_OnFeatureToggle; static Handle g_hGlobalForward_OnFeatureRegistered; static Handle g_hGlobalForward_OnFeatureUnregistered; static Handle g_hGlobalForward_OnClientDisconnect; +static Handle g_hGlobalForward_OnClientStorageLoaded; +static Handle g_hGlobalForward_OnConfigsLoaded; void API_SetupForwards() { @@ -26,6 +30,8 @@ void API_SetupForwards() g_hGlobalForward_OnFeatureRegistered = CreateGlobalForward("VIP_OnFeatureRegistered", ET_Ignore, Param_String); g_hGlobalForward_OnFeatureUnregistered = CreateGlobalForward("VIP_OnFeatureUnregistered", ET_Ignore, Param_String); g_hGlobalForward_OnClientDisconnect = CreateGlobalForward("VIP_OnClientDisconnect", ET_Ignore, Param_Cell, Param_Cell); + g_hGlobalForward_OnClientStorageLoaded = CreateGlobalForward("VIP_OnClientStorageLoaded", ET_Ignore, Param_Cell); + g_hGlobalForward_OnConfigsLoaded = CreateGlobalForward("VIP_OnConfigsLoaded", ET_Ignore); } // Global Forwards @@ -36,9 +42,16 @@ void CallForward_OnVIPLoaded() Call_Finish(); } +void CallForward_OnConfigsLoaded() +{ + DBG_API("CallForward_OnConfigsLoaded()") + Call_StartForward(g_hGlobalForward_OnConfigsLoaded); + Call_Finish(); +} + bool CallForward_OnClientPreLoad(int iClient) { - DBG_API("g_hGlobalForward_OnClientPreLoad(%N (%d), %b)", iClient, iClient, g_iClientInfo[iClient] & IS_VIP) + DBG_API("g_hGlobalForward_OnClientPreLoad(%N (%d), %b)", iClient, iClient, IS_CLIENT_VIP(iClient)) bool bResult = true; Call_StartForward(g_hGlobalForward_OnClientPreLoad); Call_PushCell(iClient); @@ -50,10 +63,10 @@ bool CallForward_OnClientPreLoad(int iClient) void CallForward_OnClientLoaded(int iClient) { - DBG_API("CallForward_OnClientLoaded(%N (%d), %b)", iClient, iClient, g_iClientInfo[iClient] & IS_VIP) + DBG_API("CallForward_OnClientLoaded(%N (%d), %b)", iClient, iClient, IS_CLIENT_VIP(iClient)) Call_StartForward(g_hGlobalForward_OnClientLoaded); Call_PushCell(iClient); - Call_PushCell(g_iClientInfo[iClient] & IS_VIP); + Call_PushCell(IS_CLIENT_VIP(iClient)); Call_Finish(); } @@ -67,10 +80,10 @@ void CallForward_OnVIPClientLoaded(int iClient) void CallForward_OnClientDisconnect(int iClient) { - DBG_API("CallForward_OnClientDisconnect(%N (%d), %b)", iClient, iClient, g_iClientInfo[iClient] & IS_VIP) + DBG_API("CallForward_OnClientDisconnect(%N (%d), %b)", iClient, iClient, IS_CLIENT_VIP(iClient)) Call_StartForward(g_hGlobalForward_OnClientDisconnect); Call_PushCell(iClient); - Call_PushCell(g_iClientInfo[iClient] & IS_VIP); + Call_PushCell(IS_CLIENT_VIP(iClient)); Call_Finish(); } @@ -95,11 +108,11 @@ void CallForward_OnVIPClientRemoved(int iClient, const char[] sReason, int iAdmi void CallForward_OnPlayerSpawn(int iClient, int iTeam) { - DBG_API("CallForward_OnPlayerSpawn(%N (%d), %d, %b)", iClient, iClient, iTeam, g_iClientInfo[iClient] & IS_VIP) + DBG_API("CallForward_OnPlayerSpawn(%N (%d), %d, %b)", iClient, iClient, iTeam, IS_CLIENT_VIP(iClient)) Call_StartForward(g_hGlobalForward_OnPlayerSpawn); Call_PushCell(iClient); Call_PushCell(iTeam); - Call_PushCell(g_iClientInfo[iClient] & IS_VIP); + Call_PushCell(IS_CLIENT_VIP(iClient)); Call_Finish(); } @@ -118,6 +131,14 @@ Action CallForward_OnShowClientInfo(int iClient, const char[] szEvent, const cha return eResult; } +void CallForward_OnClientStorageLoaded(int iClient) +{ + DBG_API("CallForward_OnClientStorageLoaded(%N (%d))", iClient, iClient) + Call_StartForward(g_hGlobalForward_OnClientStorageLoaded); + Call_PushCell(iClient); + Call_Finish(); +} + VIP_ToggleState CallForward_OnFeatureToggle(int iClient, const char[] szFeature, VIP_ToggleState eOldStatus, VIP_ToggleState eNewStatus) { DBG_API("CallForward_OnFeatureToggle(%N (%d), '%s', %d, %d)", iClient, iClient, szFeature, eOldStatus, eNewStatus) @@ -130,7 +151,7 @@ VIP_ToggleState CallForward_OnFeatureToggle(int iClient, const char[] szFeature, Call_PushCell(eOldStatus); Call_PushCellRef(eResultStatus); Call_Finish(aResult); - DBG_API("CallForward_OnShowClientInfo = %b", bResult) + DBG_API("CallForward_OnFeatureToggle = %b", bResult) switch (aResult) { @@ -250,6 +271,9 @@ public APLRes AskPluginLoad2(Handle myself, bool bLate, char[] szError, int err_ RegNative(SendClientVIPMenu); RegNative(IsValidVIPGroup); + RegNative(IsGroupExists); + RegNative(AddGroup); + RegNative(RemoveGroup); RegNative(GetClientFeatureStatus); RegNative(SetClientFeatureStatus); @@ -264,6 +288,10 @@ public APLRes AskPluginLoad2(Handle myself, bool bLate, char[] szError, int err_ RegNative(GiveClientFeature); RegNative(RemoveClientFeature); + // Storage + RegNative(SetClientStorageValue); + RegNative(GetClientStorageValue); + // Helpers RegNative(PrintToChatClient); RegNative(PrintToChatAll); @@ -288,8 +316,6 @@ public APLRes AskPluginLoad2(Handle myself, bool bLate, char[] szError, int err_ return APLRes_Success; } -#define VIP_CLIENT(%0) (g_hFeatures[%0] && (g_iClientInfo[%0] & IS_VIP)) - public int Native_CheckClient(Handle hPlugin, int iNumParams) { DBG_API("Native_CheckClient(%d)", iNumParams) @@ -299,6 +325,8 @@ public int Native_CheckClient(Handle hPlugin, int iNumParams) { Clients_CheckVipAccess(iClient, view_as(GetNativeCell(2)), view_as(GetNativeCell(3))); } + + return 0; } public int Native_IsClientVIP(Handle hPlugin, int iNumParams) @@ -308,11 +336,12 @@ public int Native_IsClientVIP(Handle hPlugin, int iNumParams) DBG_API("iClient = %d", iClient) if (CheckValidClient(iClient, false)) { - DBG_API("IS_VIP = %b", (g_iClientInfo[iClient] & IS_VIP)) - return view_as(g_iClientInfo[iClient] & IS_VIP); + DBG_API("IS_VIP = %b", IS_CLIENT_VIP(iClient)) + DBG_API("IS_CLIENT_LOADED = %b", (g_iClientInfo[iClient] & IS_LOADED)) + return IS_CLIENT_VIP(iClient) && IS_CLIENT_LOADED(iClient); } - - return false; + + return 0; } public int Native_PrintToChatClient(Handle hPlugin, int iNumParams) @@ -322,18 +351,20 @@ public int Native_PrintToChatClient(Handle hPlugin, int iNumParams) DBG_API("iClient = %d", iClient) if (CheckValidClient(iClient, false)) { - char szMessage[256]; + char szMessage[PMP]; SetGlobalTransTarget(iClient); FormatNativeString(0, 2, 3, sizeof(szMessage), _, szMessage); Colors_Print(iClient, szMessage); } + + return 0; } public int Native_PrintToChatAll(Handle hPlugin, int iNumParams) { DBG_API("Native_PrintToChatAll(%d)", iNumParams) - char szMessage[256]; + char szMessage[PMP]; for (int i = 1; i <= MCL; ++i) { @@ -344,18 +375,21 @@ public int Native_PrintToChatAll(Handle hPlugin, int iNumParams) Colors_Print(i, szMessage); } } + + return 0; } + public int Native_LogMessage(Handle hPlugin, int iNumParams) { DBG_API("Native_LogMessage(%d)", iNumParams) - if (g_CVAR_bLogsEnable) - { - char szMessage[512]; - SetGlobalTransTarget(LANG_SERVER); - FormatNativeString(0, 1, 2, sizeof(szMessage), _, szMessage); - - LogToFile(g_szLogFile, szMessage); - } + + char szMessage[512]; + SetGlobalTransTarget(LANG_SERVER); + FormatNativeString(0, 1, 2, sizeof(szMessage), _, szMessage); + + LogToFile(g_szLogFile, szMessage); + + return 0; } public int Native_GetClientID(Handle hPlugin, int iNumParams) @@ -420,28 +454,25 @@ public int Native_SetClientVIPGroup(Handle hPlugin, int iNumParams) int iClientID; if (g_hFeatures[iClient].GetValue(KEY_CID, iClientID) && iClientID != -1) { - char szQuery[256]; + char szQuery[PMP]; FormatEx(SZF(szQuery), "UPDATE `vip_users` SET `group` = '%s' WHERE `account_id` = %d%s;", szGroup, iClientID, g_szSID); DBG_SQL_Query(szQuery) g_hDatabase.Query(SQL_Callback_ChangeClientSettings, szQuery, UID(iClient)); - if (g_CVAR_bLogsEnable) - { - char szName[MNL], szAdmin[128], szPluginName[128], szOldGroup[64]; - GetClientName(iClient, SZF(szName)); - GetPluginInfo(hPlugin, PlInfo_Name, SZF(szPluginName)); - FormatEx(SZF(szAdmin), "%T %s", "BY_PLUGIN", LANG_SERVER, szPluginName); - g_hFeatures[iClient].GetString(KEY_GROUP, SZF(szOldGroup)); - g_hFeatures[iClient].GetValue(KEY_CID, iClientID); - LogToFile(g_szLogFile, "%T", "LOG_CHANGE_GROUP", LANG_SERVER, szName, iClientID, szOldGroup, szGroup, szAdmin); - } + char szName[MNL], szAdmin[128], szPluginName[128], szOldGroup[64]; + GetClientName(iClient, SZF(szName)); + GetPluginInfo(hPlugin, PlInfo_Name, SZF(szPluginName)); + FormatEx(SZF(szAdmin), "%T %s", "BY_PLUGIN", LANG_SERVER, szPluginName); + g_hFeatures[iClient].GetString(KEY_GROUP, SZF(szOldGroup)); + g_hFeatures[iClient].GetValue(KEY_CID, iClientID); + LogToFile(g_szLogFile, "%T", "LOG_CHANGE_GROUP", LANG_SERVER, szName, iClientID, szOldGroup, szGroup, szAdmin); } - } - else - { - Clients_LoadVIPFeatures(iClient); + + return 1; } + Clients_LoadFeatures(iClient); + return 1; } @@ -479,7 +510,7 @@ public int Native_SetClientAccessTime(Handle hPlugin, int iNumParams) int iClientID; if (g_hFeatures[iClient].GetValue(KEY_CID, iClientID) && iClientID != -1) { - char szQuery[256]; + char szQuery[PMP]; FormatEx(SZF(szQuery), "UPDATE `vip_users` SET `expires` = %d WHERE `account_id` = %d%s;", iTime, iClientID, g_szSID); DBG_SQL_Query(szQuery) g_hDatabase.Query(SQL_Callback_ChangeClientSettings, szQuery, UID(iClient)); @@ -512,7 +543,7 @@ public void SQL_Callback_ChangeClientSettings(Database hOwner, DBResultSet hResu public int Native_GetVIPClientTrie(Handle hPlugin, int iNumParams) { int iClient = GetNativeCell(1); - if (CheckValidClient(iClient, false) && VIP_CLIENT(iClient)) + if (CheckValidClient(iClient, false) && g_hFeatures[iClient]) { return view_as(g_hFeatures[iClient]); } @@ -523,26 +554,30 @@ public int Native_GetVIPClientTrie(Handle hPlugin, int iNumParams) public int Native_SendClientVIPMenu(Handle hPlugin, int iNumParams) { int iClient = GetNativeCell(1); - if (CheckValidClient(iClient)) + if (!CheckValidClient(iClient)) { - bool bSelection = false; + return 0; + } - if(iNumParams == 2) - { - bSelection = view_as(GetNativeCell(2)); - } - - if(bSelection) - { - g_hVIPMenu.Display(iClient, MENU_TIME_FOREVER); - return; - } - - int iItem = 0; - g_hFeatures[iClient].GetValue(KEY_MENUITEM, iItem); + bool bSelection = false; - g_hVIPMenu.DisplayAt(iClient, iItem, MENU_TIME_FOREVER); + if (iNumParams == 2) + { + bSelection = view_as(GetNativeCell(2)); } + + if (bSelection) + { + g_hVIPMenu.Display(iClient, MENU_TIME_FOREVER); + return; + } + + int iItem = 0; + g_hFeatures[iClient].GetValue(KEY_MENUITEM, iItem); + + g_hVIPMenu.DisplayAt(iClient, iItem, MENU_TIME_FOREVER); + + return 0; } public int Native_GiveClientVIP(Handle hPlugin, int iNumParams) @@ -579,13 +614,25 @@ int API_GiveClientVIP(Handle hPlugin, { if (CheckValidClient(iClient, false) && (iAdmin < 1 || CheckValidClient(iAdmin, false))) { - if (g_iClientInfo[iClient] & IS_VIP) + + if (!UTIL_CheckValidVIPGroup(szGroup)) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid VIP-group (%s)", szGroup); + } + + if (iTime < 0) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid time (%d)", iTime); + } + + if (IS_CLIENT_VIP(iClient)) { int iClientID; g_hFeatures[iClient].GetValue(KEY_CID, iClientID); if (iClientID == -1 && bAddToDB) { - ResetClient(iClient); + Clients_ResetClient(iClient); + SET_BIT(g_iClientInfo[iClient], IS_LOADED); CallForward_OnVIPClientRemoved(iClient, "Removed for VIP-status change", iAdmin); } @@ -594,41 +641,28 @@ int API_GiveClientVIP(Handle hPlugin, return ThrowNativeError(SP_ERROR_NATIVE, "The player %L is already a VIP", iClient, iClient); } } - - if (!UTIL_CheckValidVIPGroup(szGroup)) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid VIP-group (%s)", szGroup); - } - if (iTime < 0) - { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid time (%d)", iTime); - } if (bAddToDB) { char szPluginName[128]; GetPluginInfo(hPlugin, PlInfo_Name, SZF(szPluginName)); - UTIL_ADD_VIP_PLAYER(iAdmin, iClient, _, iTime, szGroup, szPluginName); + Clients_AddVipPlayer(iAdmin, iClient, _, iTime, szGroup, szPluginName); return 0; } - if (iTime == 0) - { - Clients_CreateClientVIPSettings(iClient, iTime); - } - else + + int iExpires = iTime; + + if (iTime != 0) { int iCurrentTime = GetTime(); - Clients_CreateClientVIPSettings(iClient, iTime+iCurrentTime); - Clients_CreateExpiredTimer(iClient, iTime+iCurrentTime, iCurrentTime); + iExpires = iTime + iCurrentTime; + Clients_CreateExpiredTimer(iClient, iExpires, iCurrentTime); } - g_hFeatures[iClient].SetString(KEY_GROUP, szGroup); - g_hFeatures[iClient].SetValue(KEY_CID, -1); - g_iClientInfo[iClient] |= IS_VIP; - g_iClientInfo[iClient] |= IS_LOADED; + Clients_InitVIPClient(iClient, -1, szGroup, iExpires); - Clients_LoadVIPFeatures(iClient); + Clients_TryLoadFeatures(iClient); DisplayClientInfo(iClient, iTime == 0 ? "connect_info_perm":"connect_info_time"); @@ -681,18 +715,20 @@ int API_RemoveClientVIP(Handle hPlugin, int iClientID; if (g_hFeatures[iClient].GetValue(KEY_CID, iClientID) && iClientID != -1) { - DB_RemoveClientFromID(OWNER_PLUGIN, iClient, _, true, _, _, szPluginName); + Clients_RemoveVipPlayer(OWNER_PLUGIN, iClient, iClientID, bNotify, szPluginName); + return 1; } } - - if(g_iClientInfo[iClient] & IS_MENU_OPEN) + + // TODO: remake this + if (g_iClientInfo[iClient] & IS_MENU_OPEN) { CancelClientMenu(iClient); } - Features_TurnOffAll(iClient); - ResetClient(iClient); + Clients_ResetClient(iClient); + SET_BIT(g_iClientInfo[iClient], IS_LOADED); char szBuffer[PMP]; FormatEx(SZF(szBuffer), "Removed by %s", szPluginName); @@ -716,6 +752,49 @@ public int Native_IsValidVIPGroup(Handle hPlugin, int iNumParams) return UTIL_CheckValidVIPGroup(szGroup); } +public int Native_IsGroupExists(Handle hPlugin, int iNumParams) +{ + char szGroup[64]; + GetNativeString(1, SZF(szGroup)); + return UTIL_CheckValidVIPGroup(szGroup); +} + +public int Native_AddGroup(Handle hPlugin, int iNumParams) +{ + char szGroup[64]; + GetNativeString(1, SZF(szGroup)); + if (UTIL_CheckValidVIPGroup(szGroup)) + { + return 0; + } + + g_hGroups.Rewind(); + if (g_hGroups.JumpToKey(szGroup, true)) + { + KeyValues hGroupKv = view_as(GetNativeCell(2)); + KvCopySubkeys(hGroupKv, g_hGroups); + g_hGroups.Rewind(); + return 1; + } + + return 0; +} + + +public int Native_RemoveGroup(Handle hPlugin, int iNumParams) +{ + char szGroup[64]; + GetNativeString(1, SZF(szGroup)); + if (UTIL_CheckValidVIPGroup(szGroup)) + { + g_hGroups.DeleteThis(); + g_hGroups.Rewind(); + return 1; + } + + return 0; +} + public int Native_IsVIPLoaded(Handle hPlugin, int iNumParams) { return ((GLOBAL_INFO & IS_STARTED) && g_hDatabase); @@ -736,6 +815,7 @@ public int Native_RegisterFeature(Handle hPlugin, int iNumParams) { return ThrowNativeError(SP_ERROR_NATIVE, "Feature \"%s\" already defined", szFeature); } + if (g_hFeaturesArray.Length == 0) { g_hVIPMenu.RemoveItem(0); @@ -757,10 +837,13 @@ public int Native_RegisterFeature(Handle hPlugin, int iNumParams) if (eType != HIDE) { Handle hCookie = null; + + #if USE_CLIENTPREFS 1 if (eType == TOGGLABLE || (eType == SELECTABLE && iNumParams > 7 && GetNativeCell(8))) { hCookie = RegClientCookie(szFeature, szFeature, CookieAccess_Private); } + #endif Function fCallback = GetNativeCell(4); if (eType == SELECTABLE && fCallback == INVALID_FUNCTION) @@ -776,25 +859,25 @@ public int Native_RegisterFeature(Handle hPlugin, int iNumParams) hDataPack.WriteFunction(GetNativeCell(6)); hArray.Push(hDataPack); - if(eType == TOGGLABLE) + if (eType == TOGGLABLE) { - hArray.Push(iNumParams > 6 ? GetNativeCell(7):NO_ACCESS); + hArray.Push(iNumParams > 6 ? GetNativeCell(7) : NO_ACCESS); } AddFeatureToVIPMenu(szFeature); } + CallForward_OnFeatureRegistered(szFeature); + DebugMessage("Feature \"%s\" registered", szFeature) + for (int iClient = 1; iClient <= MaxClients; ++iClient) { - if (IsClientInGame(iClient) && g_iClientInfo[iClient] & IS_VIP) + if (IsClientInGame(iClient) && VIP_CLIENT(iClient)) { - Clients_LoadVIPFeaturesPre(iClient, szFeature); + Clients_TryLoadFeature(iClient, szFeature); } } - CallForward_OnFeatureRegistered(szFeature); - DebugMessage("Feature \"%s\" registered", szFeature) - return 1; } @@ -885,16 +968,11 @@ void UnregisterFeature(const char[] szFeature, ArrayList hArray) break; } } - - if (g_hVIPMenu.ItemCount == 0) - { - g_hVIPMenu.AddItem("NO_FEATURES", "NO_FEATURES", ITEMDRAW_DISABLED); - } } for (int j = 1; j <= MaxClients; ++j) { - if (IsClientInGame(j) && g_iClientInfo[j] & IS_VIP) + if (IsClientInGame(j) && IS_CLIENT_VIP(j)) { g_hFeatures[j].Remove(szFeature); g_hFeatureStatus[j].Remove(szFeature); @@ -903,6 +981,8 @@ void UnregisterFeature(const char[] szFeature, ArrayList hArray) CallForward_OnFeatureUnregistered(szFeature); DebugMessage("Feature \"%s\" unregistered", szFeature) + + return 0; } public int Native_IsValidFeature(Handle hPlugin, int iNumParams) @@ -1003,7 +1083,7 @@ public int Native_SetClientFeatureStatus(Handle hPlugin, int iNumParams) { if (view_as(hArray.Get(FEATURES_ITEM_TYPE)) == TOGGLABLE) { - if(iNumParams > 3 && GetNativeCell(4)) + if (iNumParams > 3 && GetNativeCell(4)) { DataPack hDataPack = view_as(hArray.Get(FEATURES_MENU_CALLBACKS)); hDataPack.Position = ITEM_SELECT; @@ -1017,10 +1097,9 @@ public int Native_SetClientFeatureStatus(Handle hPlugin, int iNumParams) if (eOldStatus != eNewStatus) { Features_SetStatus(iClient, szFeature, eNewStatus); - if(iNumParams > 4 && GetNativeCell(5)) + if (iNumParams > 4 && GetNativeCell(5)) { - IntToString(view_as(eNewStatus), SZF(szFeature)); - SetClientCookie(iClient, view_as(GetArrayCell(hArray, FEATURES_COOKIE)), szFeature); + Features_SetStatusToStorage(iClient, szFeature, eNewStatus); } return true; } @@ -1084,7 +1163,7 @@ public int Native_GetClientFeatureString(Handle hPlugin, int iNumParams) int iLen = GetNativeCell(4); if (CheckValidClient(iClient, false) && VIP_CLIENT(iClient)) { - char szFeature[64], szBuffer[256]; + char szFeature[64], szBuffer[PMP]; GetNativeString(2, SZF(szFeature)); if (g_hFeatures[iClient].GetString(szFeature, SZF(szBuffer))) @@ -1111,14 +1190,15 @@ public int Native_GiveClientFeature(Handle hPlugin, int iNumParams) return ThrowNativeError(SP_ERROR_NATIVE, "Feature \"%s\" is invalid", szFeature); } - char szValue[256]; + char szValue[PMP]; GetNativeString(3, SZF(szValue)); - if (!(g_iClientInfo[iClient] & IS_VIP)) + if ((IS_CLIENT_VIP(iClient)) { - Clients_CreateClientVIPSettings(iClient, 0); + Clients_InitVIPClient(iClient, -1, NULL_STRING, 0); g_hFeatures[iClient].SetValue(KEY_CID, -1); - g_iClientInfo[iClient] |= IS_VIP|IS_LOADED; + SET_BIT(g_iClientInfo[iClient], IS_VIP); + SET_BIT(g_iClientInfo[iClient], IS_LOADED); } switch (view_as(hArray.Get(FEATURES_VALUE_TYPE))) @@ -1183,10 +1263,13 @@ public int Native_RemoveClientFeature(Handle hPlugin, int iNumParams) g_hFeatures[iClient].Remove(szFeature); g_hFeatureStatus[iClient].Remove(szFeature); + /* if (!g_hFeatures[iClient].Size) { - ResetClient(iClient); + Clients_ResetClient(iClient); + SET_BIT(g_iClientInfo[iClient], IS_LOADED); } + */ if (eToggleState != NO_ACCESS && view_as(hArray.Get(FEATURES_ITEM_TYPE)) == TOGGLABLE) { @@ -1204,6 +1287,40 @@ public int Native_RemoveClientFeature(Handle hPlugin, int iNumParams) return 1; } +public int Native_SetClientStorageValue(Handle hPlugin, int iNumParams) +{ + int iClient = GetNativeCell(1); + if (!CheckValidClient(iClient, false)) + { + return 0; + } + + char szKey[128], szValue[PMP]; + GetNativeString(2, SZF(szKey)); + GetNativeString(3, SZF(szValue)); + + Storage_SetClientValue(iClient, szKey, szValue); + + return 0; +} + +public int Native_GetClientStorageValue(Handle hPlugin, int iNumParams) +{ + int iClient = GetNativeCell(1); + if (!CheckValidClient(iClient, false)) + { + return 0; + } + + char szKey[128], szValue[PMP]; + GetNativeString(2, SZF(szKey)); + + Storage_GetClientValue(iClient, szKey, SZF(szValue)); + SetNativeString(3, szValue, GetNativeCell(4), true); + + return 0; +} + public int Native_GetDatabase(Handle hPlugin, int iNumParams) { return view_as(CloneHandle(g_hDatabase, hPlugin)); @@ -1284,14 +1401,14 @@ bool CheckValidClient(const int &iClient, bool bCheckVIP = true) ThrowNativeError(SP_ERROR_NATIVE, "Client %i is not loaded", iClient); return false; } - if (!(g_iClientInfo[iClient] & IS_VIP) || !(g_iClientInfo[iClient] & IS_AUTHORIZED)) + if (!IS_CLIENT_VIP(iClient) || !(g_iClientInfo[iClient] & IS_AUTHORIZED)) { ThrowNativeError(SP_ERROR_NATIVE, "Client %i is not VIP", iClient); return false; } */ - return view_as(g_iClientInfo[iClient] & IS_VIP); + return IS_CLIENT_VIP(iClient); } return true; diff --git a/addons/sourcemod/scripting/vip/AdminMenu.sp b/addons/sourcemod/scripting/vip/AdminMenu.sp index f177a62..2a01edc 100644 --- a/addons/sourcemod/scripting/vip/AdminMenu.sp +++ b/addons/sourcemod/scripting/vip/AdminMenu.sp @@ -67,16 +67,6 @@ void InitiateDataMap(int iClient) } } -int IsClientOnline(int ID) -{ - int iClientID; - for (int i = 1; i <= MaxClients; ++i) - { - if (IsClientInGame(i) && g_hFeatures[i] != null && g_hFeatures[i].GetValue(KEY_CID, iClientID) && iClientID == ID) return i; - } - return 0; -} - // ************************ ADMIN_MENU ************************ void VIPAdminMenu_Setup() { @@ -180,12 +170,7 @@ public void OnAdminMenuReady(Handle aTopMenu) } g_hTopMenu = hTopMenu; - - /*if (g_CVAR_bAddItemToAdminMenu) - { - AddItemsToTopMenu(); - } - */ + AddItemsToTopMenu(); } // g_CVAR_iAdminFlag @@ -385,10 +370,7 @@ public int MenuHandler_TimeMenu(Menu hMenu, MenuAction action, int iClient, int FormatTime(SZF(szTime), "%d/%m/%Y - %H:%M", iExpires); VIP_PrintToChatClient(iClient, "%t", "ADMIN_SET_EXPIRATION", szName, szTime); - if (g_CVAR_bLogsEnable) - { - LogToFile(g_szLogFile, "%T", "LOG_ADMIN_SET_EXPIRATION", LANG_SERVER, iClient, szName, szTime); - } + LogToFile(g_szLogFile, "%T", "LOG_ADMIN_SET_EXPIRATION", LANG_SERVER, iClient, szName, szTime); } case TIME_ADD: { @@ -405,10 +387,7 @@ public int MenuHandler_TimeMenu(Menu hMenu, MenuAction action, int iClient, int UTIL_GetTimeFromStamp(SZF(szTime), iTime, iClient); VIP_PrintToChatClient(iClient, "%t", "ADMIN_EXTENDED", szName, szTime); - if (g_CVAR_bLogsEnable) - { - LogToFile(g_szLogFile, "%T", "LOG_ADMIN_EXTENDED", LANG_SERVER, iClient, szName, szTime); - } + LogToFile(g_szLogFile, "%T", "LOG_ADMIN_EXTENDED", LANG_SERVER, iClient, szName, szTime); } case TIME_TAKE: { @@ -433,10 +412,7 @@ public int MenuHandler_TimeMenu(Menu hMenu, MenuAction action, int iClient, int VIP_PrintToChatClient(iClient, "%t", "ADMIN_REDUCED", szName, szTime); - if (g_CVAR_bLogsEnable) - { - LogToFile(g_szLogFile, "%T", "LOG_ADMIN_REDUCED", LANG_SERVER, iClient, szName, szTime); - } + LogToFile(g_szLogFile, "%T", "LOG_ADMIN_REDUCED", LANG_SERVER, iClient, szName, szTime); } } @@ -469,7 +445,7 @@ void ShowGroupsMenu(int iClient, const char[] sTargetGroup = NULL_STRING) { if (g_hGroups.GetSectionName(SZF(szGroup))) { - if(sTargetGroup[0] && !strcmp(sTargetGroup, szGroup)) + if (sTargetGroup[0] && !strcmp(sTargetGroup, szGroup)) { Format(SZF(szGroup), "%s [X]", szGroup); hMenu.AddItem(szGroup, szGroup, ITEMDRAW_DISABLED); @@ -530,7 +506,7 @@ public int MenuHandler_GroupsList(Menu hMenu, MenuAction action, int iClient, in { g_hClientData[iClient].GetValue(DATA_KEY_Time, iBuffer); g_hClientData[iClient].Clear(); - UTIL_ADD_VIP_PLAYER(iClient, iTarget, _, iBuffer, szGroup); + Clients_AddVipPlayer(iClient, iTarget, _, iBuffer, szGroup); } else { @@ -541,7 +517,7 @@ public int MenuHandler_GroupsList(Menu hMenu, MenuAction action, int iClient, in } case MENU_TYPE_EDIT: { - char szQuery[256], szName[MNL], szOldGroup[64]; + char szQuery[PMP], szName[MNL], szOldGroup[64]; hMenu.GetItem(Item, SZF(szGroup)); int iTargetID; g_hClientData[iClient].GetValue(DATA_KEY_TargetID, iTargetID); @@ -558,30 +534,31 @@ public int MenuHandler_GroupsList(Menu hMenu, MenuAction action, int iClient, in iTarget = CID(iTarget); if (!iTarget) { - iTarget = IsClientOnline(iTargetID); + iTarget = UTIL_GetVipClientByAccountID(iTargetID); } if (iTarget) { - ResetClient(iTarget); - CallForward_OnVIPClientRemoved(iTarget, "VIP-Group Changed", iClient); + //Clients_ResetClient(iTarget); + //SET_BIT(g_iClientInfo[iTarget], IS_LOADED); + //CallForward_OnVIPClientRemoved(iTarget, "VIP-Group Changed", iClient); Clients_CheckVipAccess(iTarget, false); } VIP_PrintToChatClient(iClient, "%t", "ADMIN_SET_GROUP", szName, szGroup); - if (g_CVAR_bLogsEnable) - { - char szAdmin[256], szAdminInfo[128]; - UTIL_GetClientInfo(iClient, SZF(szAdminInfo)); - FormatEx(SZF(szAdmin), "%T %s", "BY_ADMIN", LANG_SERVER, szAdminInfo); - LogToFile(g_szLogFile, "%T", "LOG_CHANGE_GROUP", LANG_SERVER, szName, iTargetID, szOldGroup, szGroup, szAdmin); - } + + char szAdmin[PMP], szAdminInfo[128]; + UTIL_GetClientInfo(iClient, SZF(szAdminInfo)); + FormatEx(SZF(szAdmin), "%T %s", "BY_ADMIN", LANG_SERVER, szAdminInfo); + LogToFile(g_szLogFile, "%T", "LOG_CHANGE_GROUP", LANG_SERVER, szName, iTargetID, szOldGroup, szGroup, szAdmin); ShowTargetInfo(iClient); } } } } + + return 0; } public void SQL_Callback_ChangeTime(Database hOwner, DBResultSet hResult, const char[] szError, any UserID) @@ -603,10 +580,10 @@ public void SQL_Callback_ChangeTime(Database hOwner, DBResultSet hResult, const int iTarget; g_hClientData[iClient].GetValue(DATA_KEY_TargetUID, iTarget); iTarget = CID(iTarget); - if(!iTarget) + if (!iTarget) { g_hClientData[iClient].GetValue(DATA_KEY_TargetID, iTarget); - iTarget = IsClientOnline(iTarget); + iTarget = UTIL_GetVipClientByAccountID(iTarget); } if (iTarget) diff --git a/addons/sourcemod/scripting/vip/CMD.sp b/addons/sourcemod/scripting/vip/CMD.sp index c5e44dd..3fe08d0 100644 --- a/addons/sourcemod/scripting/vip/CMD.sp +++ b/addons/sourcemod/scripting/vip/CMD.sp @@ -10,7 +10,7 @@ void CMD_Setup() #endif } -public void OnConfigsExecuted() +public void CMD_Register() { static bool bIsRegistered; if (bIsRegistered == false) @@ -46,7 +46,7 @@ public Action ReloadVIPPlayers_CMD(int iClient, int iArgs) { CHECK_ACCESS(iClient) - UTIL_ReloadVIPPlayers(iClient, true); + Clients_ReloadVipPlayers(iClient, true); return Plugin_Handled; } @@ -56,7 +56,7 @@ public Action ReloadVIPCfg_CMD(int iClient, int iArgs) CHECK_ACCESS(iClient) ReadConfigs(); - UTIL_ReloadVIPPlayers(iClient, false); + Clients_ReloadVipPlayers(iClient, false); UTIL_Reply(iClient, "%t", "VIP_CFG_REFRESHED"); return Plugin_Handled; @@ -79,7 +79,7 @@ public Action AddVIP_CMD(int iClient, int iArgs) bool bIsMulti; int iTargets, iAccountID = 0; - if((iTargets = ProcessTargetString( + if ((iTargets = ProcessTargetString( szBuffer, iClient, iTargetList, @@ -89,7 +89,7 @@ public Action AddVIP_CMD(int iClient, int iArgs) bIsMulti)) < 1) { iAccountID = UTIL_GetAccountIDFromSteamID(szBuffer); - if(!iAccountID) + if (!iAccountID) { ReplyToTargetError(iClient, iTargets); return Plugin_Handled; @@ -113,26 +113,26 @@ public Action AddVIP_CMD(int iClient, int iArgs) return Plugin_Handled; } - if(iTargets > 0) + if (iTargets > 0) { for(int i = 0; i < iTargets; ++i) { - if(IsClientInGame(iTargetList[i])) + if (IsClientInGame(iTargetList[i])) { - if (g_iClientInfo[iTargetList[i]] & IS_VIP) + if (IS_CLIENT_VIP(iTargetList[i])) { ReplyToCommand(iClient, "[VIP] %t", "ALREADY_HAS_VIP"); continue; } - UTIL_ADD_VIP_PLAYER(iClient, iTargetList[i], _, UTIL_TimeToSeconds(iTime), szGroup); + Clients_AddVipPlayer(iClient, iTargetList[i], _, UTIL_TimeToSeconds(iTime), szGroup); } } return Plugin_Handled; } - UTIL_ADD_VIP_PLAYER(iClient, _, iAccountID, UTIL_TimeToSeconds(iTime), szGroup); + Clients_AddVipPlayer(iClient, _, iAccountID, UTIL_TimeToSeconds(iTime), szGroup); return Plugin_Handled; } @@ -151,7 +151,7 @@ public Action DelVIP_CMD(int iClient, int iArgs) GetCmdArg(1, SZF(szAuth)); int iAccountID = UTIL_GetAccountIDFromSteamID(szAuth); - if(!iAccountID) + if (!iAccountID) { ReplyToTargetError(iClient, COMMAND_TARGET_NONE); return Plugin_Handled; @@ -189,14 +189,31 @@ public void SQL_Callback_OnSelectRemoveClient(Database hOwner, DBResultSet hResu if (hResult.FetchRow()) { - DBG_SQL_Response("hResult.FetchRow()") - int iAccountID = hResult.FetchInt(0); - DBG_SQL_Response("hResult.FetchInt(0) = %d", iAccountID) - char szName[MNL], szGroup[64]; + int iAccountID; + char szName[MNL*2], szGroup[64], szAdminInfo[128], szTargetInfo[128], szAuth[32]; + UTIL_GetClientInfo(iClient, SZF(szTargetInfo)); + FormatEx(SZF(szAdminInfo), "%T %s", "BY_ADMIN", LANG_SERVER, szTargetInfo); + + iAccountID = hResult.FetchInt(0); hResult.FetchString(1, SZF(szName)); hResult.FetchString(2, SZF(szGroup)); - DBG_SQL_Response("hResult.FetchString(1) = '%s", szName) - DB_RemoveClientFromID(iClient, _, iAccountID, true, szName, szGroup); + + DBG_SQL_Response("hResult.FetchInt(0) = %d", iAccountID) + DBG_SQL_Response("hResult.FetchString(1) = '%s'", szName) + DBG_SQL_Response("hResult.FetchString(2) = '%s'", szGroup) + + UTIL_GetSteamIDFromAccountID(iAccountID, SZF(szAuth)); + FormatEx(SZF(szTargetInfo), "%s (%s, unknown)", szName, szAuth); + + DB_RemoveVipPlayerByData( + iClient, + szAdminInfo, + 0, + iAccountID, + szTargetInfo, + szGroup, + true + ); } else { @@ -210,13 +227,13 @@ public Action DumpFeatures_CMD(int iClient, int iArgs) CHECK_ACCESS(iClient) int iFeatures = g_hFeaturesArray.Length; - if(iFeatures != 0) + if (iFeatures != 0) { char szBuffer[PLATFORM_MAX_PATH]; BuildPath(Path_SM, SZF(szBuffer), "data/vip/features_dump.txt"); File hFile = OpenFile(szBuffer, "w"); - if(hFile != null) + if (hFile != null) { char szPluginName[64]; char szPluginPath[PLATFORM_MAX_PATH]; @@ -230,7 +247,7 @@ public Action DumpFeatures_CMD(int iClient, int iArgs) for(int i = 0; i < iFeatures; ++i) { g_hFeaturesArray.GetString(i, SZF(szFeature)); - if(GLOBAL_TRIE.GetValue(szFeature, hArray)) + if (GLOBAL_TRIE.GetValue(szFeature, hArray)) { hPlugin = view_as(hArray.Get(FEATURES_PLUGIN)); GetPluginInfo(hPlugin, PlInfo_Name, SZF(szPluginName)); @@ -267,24 +284,17 @@ public Action DumpFeatures_CMD(int iClient, int iArgs) public Action VIPMenu_CMD(int iClient, int iArgs) { - if (iClient) + if (iClient && !IsVipMenuFlood(iClient)) { - if (OnVipMenuFlood(iClient) == false) + if (!IS_CLIENT_VIP(iClient)) { - if (g_iClientInfo[iClient] & IS_VIP) - { - g_hVIPMenu.Display(iClient, MENU_TIME_FOREVER); - } - else - { - /* - PrintToChat(iClient, "%t%t", "VIP_CHAT_PREFIX", "COMMAND_NO_ACCESS"); - */ - - PlaySound(iClient, NO_ACCESS_SOUND); - DisplayClientInfo(iClient, "no_access_info"); - } + PlaySound(iClient, NO_ACCESS_SOUND); + DisplayClientInfo(iClient, "no_access_info"); + return Plugin_Handled; } + + DisplayVipMenu(iClient); } + return Plugin_Handled; } diff --git a/addons/sourcemod/scripting/vip/Clients.sp b/addons/sourcemod/scripting/vip/Clients.sp index a9cf774..2c36319 100644 --- a/addons/sourcemod/scripting/vip/Clients.sp +++ b/addons/sourcemod/scripting/vip/Clients.sp @@ -1,8 +1,8 @@ -void ResetClient(int iClient) +void Clients_ResetClient(int iClient) { - g_iClientInfo[iClient] = IS_LOADED; - + g_iClientInfo[iClient] = 0; + UTIL_CloseHandleEx(g_hFeatures[iClient]); UTIL_CloseHandleEx(g_hFeatureStatus[iClient]); } @@ -10,12 +10,15 @@ void ResetClient(int iClient) public void OnClientPutInServer(int iClient) { // g_iClientInfo[iClient] = 0; - DebugMessage("OnClientPutInServer %N (%d): %b", iClient, iClient, g_iClientInfo[iClient]) + DBG_CLIENTS("OnClientPutInServer %N (%d): %b", iClient, iClient, g_iClientInfo[iClient]) - if(!IsFakeClient(iClient) && !IsClientSourceTV(iClient)) + if (IsFakeClient(iClient) || IsClientSourceTV(iClient)) { - Clients_CheckVipAccess(iClient, true, true); + return; } + + Storage_LoadClient(iClient); + Clients_CheckVipAccess(iClient, true, true); } public void OnClientDisconnect(int iClient) @@ -25,35 +28,38 @@ public void OnClientDisconnect(int iClient) SaveClient(iClient); }*/ - if(!IsFakeClient(iClient)) + if (!IsFakeClient(iClient)) { CallForward_OnClientDisconnect(iClient); + Storage_SaveClient(iClient); } - - ResetClient(iClient); + + Clients_ResetClient(iClient); UTIL_CloseHandleEx(g_hClientData[iClient]); g_iClientInfo[iClient] = 0; + + Storage_ResetClient(iClient); } void Clients_CheckVipAccess(int iClient, bool bNotify = false, bool bForward = false) { - if(bForward && !CallForward_OnClientPreLoad(iClient)) + if (bForward && !CallForward_OnClientPreLoad(iClient)) { return; } - g_iClientInfo[iClient] &= ~IS_LOADED; - - ResetClient(iClient); + Clients_ResetClient(iClient); + + // UNSET_BIT(g_iClientInfo[iClient], IS_LOADED); if (IsFakeClient(iClient) == false && (GLOBAL_INFO & IS_STARTED) && g_hDatabase) { Clients_LoadClient(iClient, bNotify); - // DebugMessage("Clients_CheckVipAccess %N:\tИгрок %sявляется VIP игроком", iClient, g_bIsClientVIP[iClient] ? "":"не ") + // DBG_CLIENTS("Clients_CheckVipAccess %N:\tИгрок %sявляется VIP игроком", iClient, g_bIsClientVIP[iClient] ? "":"не ") } else { - g_iClientInfo[iClient] |= IS_LOADED; + SET_BIT(g_iClientInfo[iClient], IS_LOADED); CallForward_OnClientLoaded(iClient); } } @@ -64,22 +70,12 @@ void Clients_LoadClient(int iClient, bool bNotify) int iAccountID = GetSteamAccountID(iClient); - DebugMessage("Clients_LoadClient %N (%d), %b: - > %x, %u", iClient, iClient, g_iClientInfo[iClient], g_hDatabase, g_hDatabase) - - char szWhere[64]; - if(g_szSID[0]) - { - #if USE_MORE_SERVERS 1 - FormatEx(SZF(szWhere), " AND (`sid` = %d OR `sid` = 0)", g_CVAR_iServerID); - #else - strcopy(SZF(szWhere), g_szSID); - #endif - } + DBG_CLIENTS("Clients_LoadClient %N (%d), %b: - > %x, %u", iClient, iClient, g_iClientInfo[iClient], g_hDatabase, g_hDatabase) FormatEx(SZF(szQuery), "SELECT `expires`, `group`, `name` \ FROM `vip_users` \ WHERE `account_id` = %d%s LIMIT 1;", - iAccountID, szWhere); + iAccountID, g_szSID); DataPack hDataPack = new DataPack(); hDataPack.WriteCell(UID(iClient)); @@ -108,181 +104,223 @@ public void SQL_Callback_OnClientAuthorized(Database hOwner, DBResultSet hResult bool bNotify = view_as(hDataPack.ReadCell()); delete hDataPack; - DebugMessage("SQL_Callback_OnClientAuthorized: %d", iClient) + DBG_CLIENTS("SQL_Callback_OnClientAuthorized: %d", iClient) if (!iClient || !IsClientInGame(iClient)) { return; } - if (hResult.FetchRow()) + if (!hResult.FetchRow()) { - DBG_SQL_Response("hResult.FetchRow()") - - int iExpires = hResult.FetchInt(0); - DBG_SQL_Response("hResult.FetchInt(0) = %d", iExpires) - if (iExpires > 0) - { - int iTime = GetTime(); - - if (iTime > iExpires) - { - if (g_CVAR_iDeleteExpired == 0 || (g_CVAR_iDeleteExpired > 0 && iTime >= ((g_CVAR_iDeleteExpired * 86400) + iExpires))) - { - if (g_CVAR_bLogsEnable) - { - LogToFile(g_szLogFile, "%T", "REMOVING_PLAYER", LANG_SERVER, iClient); - } + OnClientLoaded(iClient); + return; + } + DBG_SQL_Response("hResult.FetchRow()") - DebugMessage("Clients_LoadClient %N (%d):\tDelete", iClient, iClient) + int iExpires = hResult.FetchInt(0); + DBG_SQL_Response("hResult.FetchInt(0) = %d", iExpires) + char szGroup[64]; + hResult.FetchString(1, SZF(szGroup)); + DBG_SQL_Response("hResult.FetchString(1) = '%s", szGroup) - char szGroup[64]; - hResult.FetchString(1, SZF(szGroup)); + + LoadClient(iClient, iAccountID, szGroup, iExpires); - DB_RemoveClientFromID(REASON_EXPIRED, iClient, iAccountID, false, _, szGroup); - } + if (IS_CLIENT_VIP(iClient)) + { + char szName[MAX_NAME_LENGTH*2+1]; + hResult.FetchString(2, SZF(szName)); + DB_UpdateClient(iClient, szName); - CallForward_OnVIPClientRemoved(iClient, "Expired"); - - DisplayClientInfo(iClient, "expired_info"); - - g_iClientInfo[iClient] |= IS_LOADED; - CallForward_OnClientLoaded(iClient); - return; + if (bNotify) + { + if (g_CVAR_bAutoOpenMenu) + { + g_hVIPMenu.Display(iClient, MENU_TIME_FOREVER); } - - Clients_CreateExpiredTimer(iClient, iExpires, iTime); - } - char szGroup[64]; - hResult.FetchString(1, SZF(szGroup)); - DBG_SQL_Response("hResult.FetchString(1) = '%s", szGroup) - if (szGroup[0] && UTIL_CheckValidVIPGroup(szGroup)) - { - Clients_CreateClientVIPSettings(iClient, iExpires); + DisplayClientInfo(iClient, iExpires == 0 ? "connect_info_perm":"connect_info_time"); + } - g_hFeatures[iClient].SetValue(KEY_CID, iAccountID); + Clients_TryLoadFeatures(iClient); + return; + } - g_hFeatures[iClient].SetString(KEY_GROUP, szGroup); - - g_iClientInfo[iClient] |= IS_VIP|IS_LOADED; + OnClientLoaded(iClient); +} - CallForward_OnClientLoaded(iClient); +void LoadClient(int iClient, int iAccountID, const char[] szGroup, int iExpires) +{ + DBG_CLIENTS("LoadClient: %d, %d, %s, %d", iClient, iAccountID, szGroup, iExpires) + if (!szGroup[0] || !UTIL_CheckValidVIPGroup(szGroup)) + { + LogError("Invalid VIP-Group/Некорректная VIP-группа: %s (Игрок: %d)", szGroup, iAccountID); + return; + } - char szName[MAX_NAME_LENGTH*2+1]; - hResult.FetchString(2, SZF(szName)); - DB_UpdateClient(iClient, szName); + if (iExpires > 0) + { + int iTime = GetTime(); - if (bNotify) + if (iTime > iExpires) + { + if (g_CVAR_iDeleteExpired == 0 || (g_CVAR_iDeleteExpired > 0 && iTime >= ((g_CVAR_iDeleteExpired * 86400) + iExpires))) { - if (g_CVAR_bAutoOpenMenu) - { - g_hVIPMenu.Display(iClient, MENU_TIME_FOREVER); - } + LogToFile(g_szLogFile, "%T", "REMOVING_PLAYER", LANG_SERVER, iClient); - DisplayClientInfo(iClient, iExpires == 0 ? "connect_info_perm":"connect_info_time"); + DBG_CLIENTS("Clients_LoadClient %N (%d): >>> Delete", iClient, iClient) + + Clients_RemoveVipPlayer(REASON_EXPIRED, iClient, iAccountID, true); } - Clients_LoadVIPFeaturesPre(iClient); - } - else - { - LogError("Invalid VIP-Group/Некорректная VIP-группа: %s (Игрок: %d)", szGroup, iAccountID); + CallForward_OnVIPClientRemoved(iClient, "Expired"); + + DisplayClientInfo(iClient, "expired_info"); + + return; } - return; + + Clients_CreateExpiredTimer(iClient, iExpires, iTime); } + Clients_InitVIPClient(iClient, iAccountID, szGroup, iExpires); +} + + +void OnClientLoaded(int iClient) +{ + SET_BIT(g_iClientInfo[iClient], IS_LOADED); CallForward_OnClientLoaded(iClient); } -void Clients_OnVIPClientLoaded(int iClient) +void OnVIPClientLoaded(int iClient) +{ + SET_BIT(g_iClientInfo[iClient], IS_LOADED); + CallForward_OnVIPClientLoaded(iClient); +} + +stock void Clients_OnVIPClientLoaded(int iClient) { Features_TurnOnAll(iClient); CallForward_OnVIPClientLoaded(iClient); } -void Clients_CreateClientVIPSettings(int iClient, int iExp) +void Clients_InitVIPClient(int iClient, int iAccountID = -1, const char[] szGroup = NULL_STRING, int iExpires = 0) { - /* + DBG_CLIENTS("Clients_InitVIPClient: %d, %d, %s, %d", iClient, iAccountID, szGroup, iExpires) g_hFeatures[iClient] = new StringMap(); g_hFeatureStatus[iClient] = new StringMap(); - */ - g_hFeatures[iClient] = CreateTrie(); - g_hFeatureStatus[iClient] = CreateTrie(); - g_hFeatures[iClient].SetValue(KEY_EXPIRES, iExp); + g_hFeatures[iClient].SetValue(KEY_EXPIRES, iExpires); + g_hFeatures[iClient].SetString(KEY_GROUP, szGroup); + g_hFeatures[iClient].SetValue(KEY_CID, iAccountID); + + SET_BIT(g_iClientInfo[iClient], IS_VIP); } -#if DEBUG_MODE 1 +#if USE_CLIENTPREFS 1 public void OnClientCookiesCached(int iClient) { - DebugMessage("OnClientCookiesCached %d %N", iClient, iClient) + DBG_CLIENTS("OnClientCookiesCached %d %N", iClient, iClient) - DebugMessage("AreClientCookiesCached %b", AreClientCookiesCached(iClient)) + DBG_CLIENTS("AreClientCookiesCached %b", AreClientCookiesCached(iClient)) + //OnClientStorageLoaded(iClient); +} +#else +public void VIP_OnClientStorageLoaded(int iClient) +{ + DBG_CLIENTS("VIP_OnClientStorageLoaded: %d %N", iClient, iClient) + //OnClientStorageLoaded(iClient); } #endif +/* +void OnClientStorageLoaded(int iClient) +{ + DBG_CLIENTS("OnClientStorageLoaded: %d %N", iClient, iClient) +} +*/ -void Clients_LoadVIPFeaturesPre(int iClient, const char[] szFeature = NULL_STRING) +bool IsClientStorageLoaded(int iClient) { - DebugMessage("Clients_LoadVIPFeaturesPre %N", iClient) + #if USE_CLIENTPREFS 1 + DBG_CLIENTS("AreClientCookiesCached: %d %N", iClient, iClient) + return AreClientCookiesCached(iClient); + #else + DBG_CLIENTS("Storage_IsClientLoaded: %d %N", iClient, iClient) + return Storage_IsClientLoaded(iClient); + #endif +} - DebugMessage("AreClientCookiesCached %b", AreClientCookiesCached(iClient)) +void Clients_TryLoadFeatures(int iClient) +{ + DBG_CLIENTS("Clients_TryLoadFeatures %L", iClient) + DBG_CLIENTS("IsClientStorageLoaded %b", IsClientStorageLoaded(iClient)) - if (!AreClientCookiesCached(iClient)) + if (!IsClientStorageLoaded(iClient)) { + // TODO: may be will add attempts counter DataPack hDataPack = new DataPack(); hDataPack.WriteCell(UID(iClient)); - if(szFeature[0]) - { - hDataPack.WriteCell(true); - hDataPack.WriteString(szFeature); - } - else - { - hDataPack.WriteCell(false); - } - CreateTimer(0.5, Timer_CheckCookies, hDataPack, TIMER_FLAG_NO_MAPCHANGE|TIMER_DATA_HNDL_CLOSE); + CreateTimer(1.0, Timer_CheckStorageLoadFeatures, hDataPack, TIMER_FLAG_NO_MAPCHANGE|TIMER_DATA_HNDL_CLOSE); + return; } + + Clients_LoadFeatures(iClient); +} - if(szFeature[0]) +public Action Timer_CheckStorageLoadFeatures(Handle hTimer, DataPack hDataPack) +{ + hDataPack.Reset(); + int iClient = CID(hDataPack.ReadCell()); + + DBG_CLIENTS("Timer_CheckStorageLoadFeatures -> iClient: %N (%d), IsClientVIP: %b", iClient, iClient, IS_CLIENT_VIP(iClient)) + if (iClient && IS_CLIENT_VIP(iClient)) { - Clients_LoadVIPFeature(iClient, szFeature); - return; + Clients_TryLoadFeatures(iClient); } - - Clients_LoadVIPFeatures(iClient); + + return Plugin_Stop; } -public Action Timer_CheckCookies(Handle hTimer, Handle hDP) + +void Clients_TryLoadFeature(int iClient, const char[] szFeature) +{ + DBG_CLIENTS("Clients_TryLoadFeature %L", iClient) + + if (!IsClientStorageLoaded(iClient)) + { + DataPack hDataPack = new DataPack(); + hDataPack.WriteCell(UID(iClient)); + hDataPack.WriteString(szFeature); + CreateTimer(1.0, Timer_CheckStorageLoadFeature, hDataPack, TIMER_FLAG_NO_MAPCHANGE|TIMER_DATA_HNDL_CLOSE); + } + + Clients_LoadFeature(iClient, szFeature); +} + +public Action Timer_CheckStorageLoadFeature(Handle hTimer, DataPack hDataPack) { - DataPack hDataPack = view_as(hDP); hDataPack.Reset(); int iClient = CID(hDataPack.ReadCell()); - DebugMessage("Timer_CheckCookies -> iClient: %N (%d), IsClientVIP: %b,", iClient, iClient, view_as(g_iClientInfo[iClient] & IS_VIP)) - if (iClient && g_iClientInfo[iClient] & IS_VIP) + DBG_CLIENTS("Timer_CheckStorageLoadFeature -> iClient: %N (%d), IsClientVIP: %b", iClient, iClient, IS_CLIENT_VIP(iClient)) + if (iClient && IS_CLIENT_VIP(iClient)) { char szFeature[FEATURE_NAME_LENGTH]; - if(hDataPack.ReadCell()) - { - hDataPack.ReadString(SZF(szFeature)); - } - else - { - szFeature[0] = 0; - } - Clients_LoadVIPFeaturesPre(iClient, szFeature); + hDataPack.ReadString(SZF(szFeature)); + Clients_LoadFeature(iClient, szFeature); } return Plugin_Stop; } -void Clients_LoadVIPFeatures(int iClient) +void Clients_LoadFeatures(int iClient) { - DebugMessage("LoadVIPFeatures %N", iClient) + DBG_CLIENTS("LoadVIPFeatures %N", iClient) int iFeaturesCount = g_hFeaturesArray.Length; - DebugMessage("FeaturesArraySize: %d", iFeaturesCount) + DBG_CLIENTS("FeaturesArraySize: %d", iFeaturesCount) if (iFeaturesCount > 0) { char szFeature[FEATURE_NAME_LENGTH]; @@ -293,23 +331,24 @@ void Clients_LoadVIPFeatures(int iClient) for (int i = 0; i < iFeaturesCount; ++i) { g_hFeaturesArray.GetString(i, SZF(szFeature)); - Clients_LoadFeature(iClient, szFeature); + Clients_LoadFeatureValue(iClient, szFeature); } } } - DebugMessage("Clients_OnVIPClientLoaded: %d %N", iClient, iClient) + DBG_CLIENTS("Clients_OnVIPClientLoaded: %d %N", iClient, iClient) - Clients_OnVIPClientLoaded(iClient); + OnClientLoaded(iClient); + OnVIPClientLoaded(iClient); + Features_TurnOnAll(iClient); } - -void Clients_LoadVIPFeature(int iClient, const char[] szFeature) +void Clients_LoadFeature(int iClient, const char[] szFeature) { - DebugMessage("LoadVIPFeature %N", iClient) + DBG_CLIENTS("LoadVIPFeature %N", iClient) int iFeaturesCount = g_hFeaturesArray.Length; - DebugMessage("FeaturesArraySize: %d", iFeaturesCount) + DBG_CLIENTS("FeaturesArraySize: %d", iFeaturesCount) if (iFeaturesCount > 0) { char szGroup[FEATURE_NAME_LENGTH]; @@ -317,48 +356,31 @@ void Clients_LoadVIPFeature(int iClient, const char[] szFeature) g_hFeatures[iClient].GetString(KEY_GROUP, SZF(szGroup)); if (UTIL_CheckValidVIPGroup(szGroup)) { - Clients_LoadFeature(iClient, szFeature); + Clients_LoadFeatureValue(iClient, szFeature); } } /* - DebugMessage("Clients_OnVIPClientLoaded: %d %N", iClient, iClient) + DBG_CLIENTS("Clients_OnVIPClientLoaded: %d %N", iClient, iClient) Clients_OnVIPClientLoaded(iClient); */ } -void Clients_LoadFeature(int iClient, const char[] szFeature) +void Clients_LoadFeatureValue(int iClient, const char[] szFeature) { static ArrayList hArray; if (GLOBAL_TRIE.GetValue(szFeature, hArray)) { - DebugMessage("LoadClientFeature: %s", szFeature) + DBG_CLIENTS("Clients_LoadFeatureValue: %s", szFeature) - if (GetValue(iClient, view_as(hArray.Get(FEATURES_VALUE_TYPE)), szFeature)) + if (GetFeatureValue(iClient, view_as(hArray.Get(FEATURES_VALUE_TYPE)), szFeature)) { - static VIP_ToggleState eStatus; - DebugMessage("GetValue: == true") + static VIP_ToggleState eStatus; + DBG_CLIENTS("GetValue: == true") if (view_as(hArray.Get(FEATURES_ITEM_TYPE)) == TOGGLABLE) { - static char szBuffer[4]; - static Handle hCookie; - hCookie = view_as(hArray.Get(FEATURES_COOKIE)); - GetClientCookie(iClient, hCookie, SZF(szBuffer)); - eStatus = view_as(StringToInt(szBuffer)); - DebugMessage("GetFeatureCookie: '%s'", szBuffer) - if (szBuffer[0] == '\0' || (view_as(eStatus) > 2 || view_as(eStatus) < 0)) - { - switch(hArray.Get(FEATURES_DEF_STATUS)) - { - case NO_ACCESS: eStatus = g_CVAR_bDefaultStatus ? ENABLED:DISABLED; - case ENABLED: eStatus = ENABLED; - case DISABLED: eStatus = DISABLED; - } - - IntToString(view_as(eStatus), SZF(szBuffer)); - SetClientCookie(iClient, hCookie, szBuffer); - // Features_SaveStatus(iClient, szFeature, hCookie, eStatus); - } + eStatus = Features_GetStatusFromStorage(iClient, szFeature, hArray); + DBG_CLIENTS("Features_GetStatusFromStorage: '%d'", eStatus) } else { @@ -371,20 +393,16 @@ void Clients_LoadFeature(int iClient, const char[] szFeature) } } -bool GetValue(int iClient, VIP_ValueType ValueType, const char[] szFeature) +bool GetFeatureValue(int iClient, VIP_ValueType ValueType, const char[] szFeature) { - DebugMessage("GetValue: %d - %s", ValueType, szFeature) + DBG_CLIENTS("GetFeatureValue: %d - %s", ValueType, szFeature) switch (ValueType) { - case VIP_NULL: - { - return false; - } case BOOL: { if (g_hGroups.GetNum(szFeature)) { - DebugMessage("value: 1") + DBG_CLIENTS("value: 1") return g_hFeatures[iClient].SetValue(szFeature, true); } return false; @@ -395,7 +413,7 @@ bool GetValue(int iClient, VIP_ValueType ValueType, const char[] szFeature) iValue = g_hGroups.GetNum(szFeature); if (iValue != 0) { - DebugMessage("value: %d", iValue) + DBG_CLIENTS("value: %d", iValue) return g_hFeatures[iClient].SetValue(szFeature, iValue); } return false; @@ -406,7 +424,7 @@ bool GetValue(int iClient, VIP_ValueType ValueType, const char[] szFeature) fValue = g_hGroups.GetFloat(szFeature); if (fValue != 0.0) { - DebugMessage("value: %f", fValue) + DBG_CLIENTS("value: %f", fValue) return g_hFeatures[iClient].SetValue(szFeature, fValue); } @@ -414,15 +432,19 @@ bool GetValue(int iClient, VIP_ValueType ValueType, const char[] szFeature) } case STRING: { - char szBuffer[256]; + char szBuffer[PMP]; g_hGroups.GetString(szFeature, SZF(szBuffer)); if (szBuffer[0]) { - DebugMessage("value: %s", szBuffer) + DBG_CLIENTS("value: %s", szBuffer) return g_hFeatures[iClient].SetString(szFeature, szBuffer); } return false; } + case VIP_NULL: + { + return false; + } } return false; @@ -432,32 +454,31 @@ void Clients_CreateExpiredTimer(int iClient, int iExp, int iTime) { int iTimeLeft; GetMapTimeLeft(iTimeLeft); - DebugMessage("Clients_CreateExpiredTimer %N (%d):\tiTimeLeft: %d", iClient, iClient, iTimeLeft) + DBG_CLIENTS("Clients_CreateExpiredTimer %N (%d): iTimeLeft: %d", iClient, iClient, iTimeLeft) if (iTimeLeft > 0) { - DebugMessage("Clients_CreateExpiredTimer %N (%d):\tiTimeLeft+iTime: %d", iClient, iClient, iTimeLeft + iTime) - if ((iTimeLeft + iTime) > iExp) + DBG_CLIENTS("Clients_CreateExpiredTimer %N (%d): iTimeLeft+iTime: %d", iClient, iClient, iTimeLeft + iTime) + if ((iTimeLeft + iTime) < iExp) { - DebugMessage("Clients_CreateExpiredTimer %N (%d):\tTimerDealy: %f", iClient, iClient, float((iExp - iTime) + 3)) - - CreateTimer(float((iExp - iTime) + 3), Timer_VIP_Expired, UID(iClient), TIMER_FLAG_NO_MAPCHANGE); + DBG_CLIENTS("Skip timer") + return; } } + + DBG_CLIENTS("Clients_CreateExpiredTimer %N (%d): TimerDealy: %f", iClient, iClient, float((iExp - iTime) + 3)) + CreateTimer(float((iExp - iTime) + 3), Timer_VIP_Expired, UID(iClient), TIMER_FLAG_NO_MAPCHANGE); } public void Event_MatchEndRestart(Event hEvent, const char[] sEvName, bool bDontBroadcast) { - if (g_CVAR_iDeleteExpired != -1 || g_CVAR_iOutdatedExpired != -1) - { - RemoveExpAndOutPlayers(); - } + RemoveExpAndOutPlayers(); } public void Event_PlayerSpawn(Event hEvent, const char[] sEvName, bool bDontBroadcast) { int UserID = hEvent.GetInt("userid"); int iClient = CID(UserID); - DebugMessage("Event_PlayerSpawn: %N (%d)", iClient, iClient) + DBG_CLIENTS("Event_PlayerSpawn: %N (%d)", iClient, iClient) if (!(g_iClientInfo[iClient] & IS_SPAWNED)) { CreateTimer(g_CVAR_fSpawnDelay, Timer_OnPlayerSpawn, UserID, TIMER_FLAG_NO_MAPCHANGE); @@ -467,7 +488,7 @@ public void Event_PlayerSpawn(Event hEvent, const char[] sEvName, bool bDontBroa public void Event_PlayerDeath(Event hEvent, const char[] sEvName, bool bDontBroadcast) { int iClient = CID(hEvent.GetInt("userid")); - DebugMessage("Event_PlayerDeath: %N (%d)", iClient, iClient) + DBG_CLIENTS("Event_PlayerDeath: %N (%d)", iClient, iClient) g_iClientInfo[iClient] &= ~IS_SPAWNED; } @@ -479,9 +500,9 @@ public Action Timer_OnPlayerSpawn(Handle hTimer, any UserID) int iTeam = GetClientTeam(iClient); if (iTeam > 1 && IsPlayerAlive(iClient)) { - DebugMessage("Timer_OnPlayerSpawn: %N (%d)", iClient, iClient) + DBG_CLIENTS("Timer_OnPlayerSpawn: %N (%d)", iClient, iClient) - if (g_iClientInfo[iClient] & IS_VIP) + if (IS_CLIENT_VIP(iClient)) { int iExp; if (g_hFeatures[iClient].GetValue(KEY_EXPIRES, iExp) && iExp > 0 && iExp < GetTime()) @@ -499,7 +520,7 @@ public Action Timer_OnPlayerSpawn(Handle hTimer, any UserID) public void Event_RoundEnd(Event hEvent, const char[] sEvName, bool bDontBroadcast) { - DebugMessage("Event_RoundEnd") + DBG_CLIENTS("Event_RoundEnd") int iTime, iExp, i; iTime = GetTime(); for (i = 1; i <= MaxClients; ++i) @@ -507,7 +528,7 @@ public void Event_RoundEnd(Event hEvent, const char[] sEvName, bool bDontBroadca if (IsClientInGame(i)) { g_iClientInfo[i] &= ~IS_SPAWNED; - if ((g_iClientInfo[i] & IS_VIP) && g_hFeatures[i].GetValue(KEY_EXPIRES, iExp) && iExp > 0 && iExp < iTime) + if (IS_CLIENT_VIP(i) && g_hFeatures[i].GetValue(KEY_EXPIRES, iExp) && iExp > 0 && iExp < iTime) { Clients_ExpiredClient(i); } @@ -517,24 +538,26 @@ public void Event_RoundEnd(Event hEvent, const char[] sEvName, bool bDontBroadca public Action Timer_VIP_Expired(Handle hTimer, any UserID) { - DebugMessage("Timer_VIP_Expired %d:", UserID) + DBG_CLIENTS("Timer_VIP_Expired %d:", UserID) int iClient = CID(UserID); - if (iClient && g_iClientInfo[iClient] & IS_VIP) + if (iClient && IS_CLIENT_VIP(iClient)) { int iExp; if (g_hFeatures[iClient].GetValue(KEY_EXPIRES, iExp) && iExp > 0 && iExp < GetTime()) { - DebugMessage("Timer_VIP_Expired %N:", iClient) + DBG_CLIENTS("Timer_VIP_Expired %N:", iClient) Clients_ExpiredClient(iClient); } } + + return Plugin_Stop; } void Clients_ExpiredClient(int iClient) { - DebugMessage("Clients_ExpiredClient %N:", iClient) + DBG_CLIENTS("Clients_ExpiredClient %N:", iClient) Features_TurnOffAll(iClient); int iClientID; @@ -543,23 +566,241 @@ void Clients_ExpiredClient(int iClient) { if (g_hFeatures[iClient].GetValue(KEY_CID, iClientID) && iClientID != -1) { - if (g_CVAR_bLogsEnable) - { - LogToFile(g_szLogFile, "%T", "REMOVING_PLAYER", LANG_SERVER, iClient); - } - - DB_RemoveClientFromID(REASON_EXPIRED, iClient, _, false); + LogToFile(g_szLogFile, "%T", "REMOVING_PLAYER", LANG_SERVER, iClient); + + Clients_RemoveVipPlayer(REASON_EXPIRED, iClient, _, true); + return; } } - if(g_iClientInfo[iClient] & IS_MENU_OPEN) + if (g_iClientInfo[iClient] & IS_MENU_OPEN) { CancelClientMenu(iClient); } - ResetClient(iClient); - + Clients_ResetClient(iClient); + SET_BIT(g_iClientInfo[iClient], IS_LOADED); + CallForward_OnVIPClientRemoved(iClient, "Expired"); - + DisplayClientInfo(iClient, "expired_info"); } + +void Clients_AddVipPlayer( + int iAdmin = OWNER_SERVER, + int iTarget = 0, + int iTargetAccountID = 0, + int iDuration, + const char[] szGroup, + const char[] szByWho = NULL_STRING +) +{ + char szAdminInfo[PMP], szTargetInfo[PMP]; + int iExpires; + + if (iDuration) + { + iExpires = iDuration + GetTime(); + } + else + { + iExpires = iDuration; + } + + if (iTarget) + { + iTargetAccountID = GetSteamAccountID(iTarget); + UTIL_GetClientInfo(iTarget, SZF(szTargetInfo)); + } + else + { + char szAuth[32]; + UTIL_GetSteamIDFromAccountID(iTargetAccountID, SZF(szAuth)); + FormatEx(SZF(szTargetInfo), "unknown (%s, unknown)", szAuth); + } + + switch(iAdmin) + { + case OWNER_PLUGIN: + { + FormatEx(SZF(szAdminInfo), "%T %s", "BY_PLUGIN", LANG_SERVER, szByWho); + } + case OWNER_SERVER: + { + FormatEx(SZF(szAdminInfo), "%T", "BY_SERVER", LANG_SERVER); + } + default: + { + char szAdmin[128]; + UTIL_GetClientInfo(iAdmin, SZF(szAdmin)); + FormatEx(SZF(szAdminInfo), "%T %s", "BY_ADMIN", LANG_SERVER, szAdmin); + iAdmin = UID(iAdmin); + } + } + + DB_AddVipPlayer( + iAdmin, + szAdminInfo, + iTarget, + iTargetAccountID, + szTargetInfo, + iDuration, + iExpires, + szGroup + ); +} + +void Clients_OnVipPlayerAdded( + const int iAdmin, + const char[] szAdminInfo, + const int iTarget, + const int iTargetAccountID, + const char[] szTargetInfo, + const int iDuration, + const int iExpires, + const char[] szGroup +) +{ + char szExpires[64], szDuration[64]; + + if (iTarget) + { + Clients_CheckVipAccess(iTarget, true); + CallForward_OnVIPClientAdded(iTarget, iAdmin); + } + + if (iAdmin >= 0) + { + if (iDuration) + { + UTIL_GetTimeFromStamp(SZF(szDuration), iDuration, iAdmin); + FormatTime(SZF(szExpires), "%d/%m/%Y - %H:%M", iExpires); + } + else + { + FormatEx(SZF(szDuration), "%T", "PERMANENT", iAdmin); + FormatEx(SZF(szExpires), "%T", "NEVER", iAdmin); + } + UTIL_Reply(iAdmin, "%t", "ADMIN_VIP_ADD_SUCCESS", szTargetInfo, szGroup); + } + + if (iDuration) + { + UTIL_GetTimeFromStamp(SZF(szExpires), iDuration, LANG_SERVER); + } + else + { + FormatEx(SZF(szExpires), "%T", "PERMANENT", LANG_SERVER); + FormatEx(SZF(szExpires), "%T", "NEVER", LANG_SERVER); + } + + LogToFile(g_szLogFile, "%T", "LOG_VIP_ADDED", LANG_SERVER, szTargetInfo, iTargetAccountID, szDuration, szExpires, szGroup, szAdminInfo); +} + +void Clients_RemoveVipPlayer( + int iAdmin = 0, + int iTarget = 0, + int iTargetAccountID = 0, + bool bNotify, + const char[] szByWho = NULL_STRING +) +{ + DBG_CLIENTS("Clients_RemoveVipPlayer %d: - > iTargetAccountID: %d, : bNotify: %b", iTarget, iTargetAccountID, bNotify) + + if (iTarget) { + iTargetAccountID = GetSteamAccountID(iTarget); + } + + char szAdminInfo[PMP]; + switch(iAdmin) + { + case REASON_EXPIRED: + { + FormatEx(SZF(szAdminInfo), "%T", "REASON_EXPIRED", LANG_SERVER); + } + case REASON_OUTDATED: + { + FormatEx(SZF(szAdminInfo), "%T", "REASON_INACTIVITY", LANG_SERVER); + } + case OWNER_PLUGIN: + { + FormatEx(SZF(szAdminInfo), "%T %s", "BY_PLUGIN", LANG_SERVER, szByWho); + } + case OWNER_SERVER: + { + FormatEx(SZF(szAdminInfo), "%T", "BY_SERVER", LANG_SERVER); + } + default: + { + char szAdmin[128]; + UTIL_GetClientInfo(iAdmin, SZF(szAdmin)); + FormatEx(SZF(szAdminInfo), "%T %s", "BY_ADMIN", LANG_SERVER, szAdmin); + } + } + + DB_RemoveVipPlayer( + iAdmin, + szAdminInfo, + iTarget, + iTargetAccountID, + bNotify + ); +} + +void Clients_OnVipPlayerRemoved( + const int iAdmin, + const char[] szAdminInfo, + const int iTarget, + const int iTargetAccountID, + const char[] szTargetInfo, + const char[] szGroup, + const bool bNotify +) +{ + LogToFile(g_szLogFile, "%T", "LOG_VIP_DELETED", LANG_SERVER, szTargetInfo, iTargetAccountID, szGroup, szAdminInfo); + + DebugMessage("Clients_OnVipPlayerRemoved(iAdmin: %d, szAdminInfo: %s, iTarget: %d, iTargetAccountID: %d, szTargetInfo: %s", iAdmin, szAdminInfo, iTarget, iTargetAccountID, szTargetInfo) + + if (iTarget) + { + if (g_iClientInfo[iTarget] & IS_MENU_OPEN) + { + CancelClientMenu(iTarget); + } + + Features_TurnOffAll(iTarget); + Clients_ResetClient(iTarget); + SET_BIT(g_iClientInfo[iTarget], IS_LOADED); + + // TODO: Fix this + CallForward_OnVIPClientRemoved(iTarget, "Expired"); + + DisplayClientInfo(iTarget, "expired_info"); + + if (bNotify) + { + // TODO: notify player + } + } + + if (iAdmin > 0) + { + UTIL_Reply(iAdmin, "%t", "ADMIN_VIP_PLAYER_DELETED", szTargetInfo, szGroup); + } +} + +void Clients_ReloadVipPlayers(int iClient, bool bNotify) +{ + for (int i = 1; i <= MaxClients; ++i) + { + if (IsClientInGame(i)) + { + Clients_CheckVipAccess(i, false, true); + } + } + + if (bNotify) + { + UTIL_Reply(iClient, "%t", "VIP_CACHE_REFRESHED"); + } +} diff --git a/addons/sourcemod/scripting/vip/Colors.sp b/addons/sourcemod/scripting/vip/Colors.sp index a0e0706..5e596e6 100644 --- a/addons/sourcemod/scripting/vip/Colors.sp +++ b/addons/sourcemod/scripting/vip/Colors.sp @@ -142,16 +142,16 @@ void Colors_RemoveColors(char[] szBuffer) for(; i < iLen; ++i) { - if(bIgnore) + if (bIgnore) { - if(szTemp[i] == '}') + if (szTemp[i] == '}') { bIgnore = false; } continue; } - if(szTemp[i] == '{') + if (szTemp[i] == '{') { bIgnore = true; continue; diff --git a/addons/sourcemod/scripting/vip/Configs.sp b/addons/sourcemod/scripting/vip/Configs.sp index d57a41b..4b1cbae 100644 --- a/addons/sourcemod/scripting/vip/Configs.sp +++ b/addons/sourcemod/scripting/vip/Configs.sp @@ -1,14 +1,3 @@ -public void OnMapStart() -{ - LoadSounds(); - ReadDownloads(); - - if (g_hDatabase && (g_CVAR_iDeleteExpired != -1 || g_CVAR_iOutdatedExpired != -1)) - { - RemoveExpAndOutPlayers(); - } -} - void OnReadyToStart() { DebugMessage("OnReadyToStart") @@ -71,6 +60,8 @@ void ReadConfigs() g_hGroups = CreateConfig("data/vip/cfg/groups.ini", "VIP_GROUPS"); g_hInfo = CreateConfig("data/vip/cfg/info.ini", "VIP_INFO"); + + CallForward_OnConfigsLoaded(); } KeyValues CreateConfig(const char[] szFile, const char[] szKvName) diff --git a/addons/sourcemod/scripting/vip/Cvars.sp b/addons/sourcemod/scripting/vip/Cvars.sp index 03c81ca..d094d98 100644 --- a/addons/sourcemod/scripting/vip/Cvars.sp +++ b/addons/sourcemod/scripting/vip/Cvars.sp @@ -22,11 +22,11 @@ void Cvars_Setup() hCvar.AddChangeHook(OnTimeModeChange); g_CVAR_iTimeMode = hCvar.IntValue; - hCvar = CreateConVar("sm_vip_delete_expired", "1", "Удалять VIP-игроков у которых истек срок (-1 - Не удалять, 0 - Удалять сразу, > 0 - Количество дней, по истечению которых удалять)", _, true, -1.0, true, 365.0); + hCvar = CreateConVar("sm_vip_delete_expired", "1", "Удалять VIP-игроков у которых истек срок и они не заходили на сервер (-1 - Не удалять, 0 - Удалять сразу, > 0 - Количество дней, по истечению которых удалять)", _, true, -1.0, true, 365.0); hCvar.AddChangeHook(OnDeleteExpiredChange); g_CVAR_iDeleteExpired = hCvar.IntValue; - hCvar = CreateConVar("sm_vip_delete_outdated", "-1", "Удалять VIP-игроков которые не заходили на сервер X дней (-1 - Не удалять, > 0 - Количество дней, по истечению которых удалять (минимум 3 суток))", _, true, -1.0, true, 365.0); + hCvar = CreateConVar("sm_vip_delete_outdated", "-1", "Удалять VIP-игроков которые не заходили на сервер X дней (-1 или 0 - Не удалять, > 0 - Количество дней, по истечению которых удалять (минимум 3 суток))", _, true, -1.0, true, 365.0); hCvar.AddChangeHook(OnDeleteOutdatedChange); g_CVAR_iOutdatedExpired = hCvar.IntValue; @@ -45,10 +45,6 @@ void Cvars_Setup() hCvar = CreateConVar("sm_vip_features_default_status", "1", "Статус функций по-умолчанию (0 - Выключены, 1 - Включены)", _, true, 0.0, true, 1.0); hCvar.AddChangeHook(OnDefaultStatusChange); g_CVAR_bDefaultStatus = hCvar.BoolValue; - - hCvar = CreateConVar("sm_vip_logs_enable", "1", "Вести ли лог logs/VIP_Logs.log (0 - Выключено, 1 - Включено)", _, true, 0.0, true, 1.0); - hCvar.AddChangeHook(OnLogsEnableChange); - g_CVAR_bLogsEnable = hCvar.BoolValue; AutoExecConfig(true, "VIP_Core", "vip"); } @@ -58,9 +54,9 @@ public void OnAdminFlagChange(ConVar hCvar, const char[] szOldValue, const char[ g_CVAR_iAdminFlag = UTIL_GetConVarAdminFlag(hCvar); #if USE_ADMINMENU 1 - if(g_hTopMenu) + if (g_hTopMenu) { - if(VIPAdminMenuObject != INVALID_TOPMENUOBJECT ) + if (VIPAdminMenuObject != INVALID_TOPMENUOBJECT) { RemoveFromTopMenu(g_hTopMenu, VIPAdminMenuObject); } @@ -105,7 +101,7 @@ public void OnTimeModeChange(ConVar hCvar, const char[] szOldValue, const char[] public void OnDeleteExpiredChange(ConVar hCvar, const char[] szOldValue, const char[] szNewValue) { g_CVAR_iDeleteExpired = hCvar.IntValue; - if(g_CVAR_iDeleteExpired < -1) + if (g_CVAR_iDeleteExpired < -1) { g_CVAR_iDeleteExpired = -1; } @@ -114,15 +110,15 @@ public void OnDeleteExpiredChange(ConVar hCvar, const char[] szOldValue, const c public void OnDeleteOutdatedChange(ConVar hCvar, const char[] szOldValue, const char[] szNewValue) { g_CVAR_iOutdatedExpired = hCvar.IntValue; - if(g_CVAR_iOutdatedExpired != -1) + if (g_CVAR_iOutdatedExpired != -1) { - if(g_CVAR_iOutdatedExpired < 1) + if (g_CVAR_iOutdatedExpired < 1) { g_CVAR_iOutdatedExpired = -1; return; } - if(g_CVAR_iOutdatedExpired < 3) + if (g_CVAR_iOutdatedExpired < 3) { g_CVAR_iOutdatedExpired = 3; } @@ -148,8 +144,3 @@ public void OnDefaultStatusChange(ConVar hCvar, const char[] szOldValue, const c { g_CVAR_bDefaultStatus = hCvar.BoolValue; } - -public void OnLogsEnableChange(ConVar hCvar, const char[] szOldValue, const char[] szNewValue) -{ - g_CVAR_bLogsEnable = hCvar.BoolValue; -} diff --git a/addons/sourcemod/scripting/vip/Database.sp b/addons/sourcemod/scripting/vip/Database.sp index 3653219..3bd1a03 100644 --- a/addons/sourcemod/scripting/vip/Database.sp +++ b/addons/sourcemod/scripting/vip/Database.sp @@ -27,13 +27,13 @@ void DB_Connect() } else { - char szError[256]; + char szError[PMP]; g_hDatabase = SQLite_UseDatabase("vip_core", SZF(szError)); OnDBConnect(g_hDatabase, szError, 1); } } -public void OnDBConnect(Database hDatabase, const char[] szError, any data) +public void OnDBConnect(Database hDatabase, const char[] szError, int data) { if (hDatabase == null || szError[0]) { @@ -80,7 +80,8 @@ void CreateTables() #else FormatEx(SZF(g_szSID), " AND `sid` = %d", g_CVAR_iServerID); #endif - g_hDatabase.Query(SQL_Callback_TableCreate, "CREATE TABLE IF NOT EXISTS `vip_users` (\ + + g_hDatabase.Query(SQL_Callback_TableCreate, "CREATE TABLE IF NOT EXISTS `vip_users` (\ `account_id` INT NOT NULL, \ `name` VARCHAR(64) NOT NULL default 'unknown' COLLATE '" ... COLLATION ... "', \ `lastvisit` INT UNSIGNED NOT NULL default 0, \ @@ -89,16 +90,34 @@ void CreateTables() `expires` INT UNSIGNED NOT NULL default 0, \ CONSTRAINT pk_PlayerID PRIMARY KEY (`account_id`, `sid`) \ ) DEFAULT CHARSET=" ... CHARSET ... ";"); + + g_hDatabase.Query(SQL_Callback_StorageTableCreate, "CREATE TABLE IF NOT EXISTS `vip_storage` (\ + `account_id` INT NOT NULL, \ + `key` VARCHAR(128) NOT NULL, \ + `value` varchar(256) NOT NULL default '', \ + `sid` INT UNSIGNED NOT NULL, \ + `updated` INT UNSIGNED NOT NULL default 0, \ + PRIMARY KEY (`account_id`, `key`, `sid`) \ + ) DEFAULT CHARSET=" ... CHARSET ... ";"); } else { g_szSID[0] = 0; - g_hDatabase.Query(SQL_Callback_TableCreate, "CREATE TABLE IF NOT EXISTS `vip_users` (\ + + g_hDatabase.Query(SQL_Callback_TableCreate, "CREATE TABLE IF NOT EXISTS `vip_users` (\ `account_id` INTEGER PRIMARY KEY NOT NULL, \ `name` VARCHAR(64) NOT NULL default 'unknown', \ `lastvisit` INTEGER UNSIGNED NOT NULL default 0, \ `group` VARCHAR(64) NOT NULL, \ `expires` INTEGER UNSIGNED NOT NULL default 0);"); + + g_hDatabase.Query(SQL_Callback_StorageTableCreate, "CREATE TABLE IF NOT EXISTS `vip_storage` (\ + `account_id` INTEGER NOT NULL, \ + `key` VARCHAR(128) NOT NULL, \ + `value` TEXT NOT NULL default '', \ + `updated` INTEGER UNSIGNED NOT NULL default 0, \ + PRIMARY KEY (`account_id`, `key`) \ + );"); } } @@ -106,7 +125,7 @@ public void SQL_Callback_TableCreate(Database hOwner, DBResultSet hResult, const { DBG_SQL_Response("SQL_Callback_TableCreate") - if (szError[0]) + if (!hResult || szError[0]) { SetFailState("SQL_Callback_TableCreate: %s", szError); return; @@ -124,28 +143,41 @@ public void SQL_Callback_TableCreate(Database hOwner, DBResultSet hResult, const OnReadyToStart(); - UTIL_ReloadVIPPlayers(0, false); + Clients_ReloadVipPlayers(0, false); - if (g_CVAR_iDeleteExpired != -1 || g_CVAR_iOutdatedExpired != -1) + RemoveExpAndOutPlayers(); +} + +public void SQL_Callback_StorageTableCreate(Database hOwner, DBResultSet hResult, const char[] szError, any data) +{ + DBG_SQL_Response("SQL_Callback_StorageTableCreate") + + if (!hResult || szError[0]) { - RemoveExpAndOutPlayers(); + SetFailState("SQL_Callback_StorageTableCreate: %s", szError); + return; } } void RemoveExpAndOutPlayers() { + DebugMessage("RemoveExpAndOutPlayers") + DebugMessage("g_CVAR_iDeleteExpired: %d", g_CVAR_iDeleteExpired) + DebugMessage("g_CVAR_iOutdatedExpired: %d", g_CVAR_iOutdatedExpired) + if (g_CVAR_iDeleteExpired >= 0) { - char szQuery[256]; - FormatEx(SZF(szQuery), "SELECT `account_id`, `name`, `group` FROM `vip_users` WHERE `expires` > 0 AND `expires` < %d%s;", GetTime() - (g_CVAR_iDeleteExpired == 0 ? 1:g_CVAR_iDeleteExpired)*86400, g_szSID); + char szQuery[PMP]; + FormatEx(SZF(szQuery), "SELECT `account_id`, `name`, `group` FROM `vip_users` WHERE `expires` > 0 AND `expires` < %d%s;", (GetTime() - g_CVAR_iDeleteExpired*86400), g_szSID); DBG_SQL_Query(szQuery) + DebugMessage(szQuery) g_hDatabase.Query(SQL_Callback_SelectExpiredAndOutdated, szQuery, REASON_EXPIRED); } if (g_CVAR_iOutdatedExpired > 0) { - char szQuery[256]; + char szQuery[PMP]; FormatEx(SZF(szQuery), "SELECT `account_id`, `name`, `group` FROM `vip_users` WHERE `lastvisit` > 0 AND `lastvisit` < %d%s;", (GetTime() - g_CVAR_iOutdatedExpired*86400), g_szSID); DBG_SQL_Query(szQuery) @@ -168,7 +200,7 @@ void DB_UpdateClient(int iClient, const char[] szDbName = NULL_STRING) int iClientID; g_hFeatures[iClient].GetValue(KEY_CID, iClientID); - char szQuery[256]; + char szQuery[PMP]; if (g_CVAR_bUpdateName || !strcmp(szDbName, "unknown")) { @@ -186,6 +218,333 @@ void DB_UpdateClient(int iClient, const char[] szDbName = NULL_STRING) g_hDatabase.Query(SQL_Callback_ErrorCheck, szQuery); } +public void SQL_Callback_SelectExpiredAndOutdated(Database hOwner, DBResultSet hResult, const char[] szError, int iReason) +{ + DBG_SQL_Response("SQL_Callback_SelectExpiredAndOutdated") + + if (szError[0]) + { + LogError("SQL_Callback_SelectExpiredAndOutdated: %s", szError); + return; + } + + DBG_SQL_Response("hResult.RowCount = %d", hResult.RowCount) + DebugMessage("hResult.RowCount = %d", hResult.RowCount) + + if (hResult.RowCount) + { + int iAccountID; + char szName[MNL*2], szGroup[64], szAdminInfo[128], szTargetInfo[128], szAuth[32]; + FormatEx(SZF(szAdminInfo), "%T", "REASON_EXPIRED", LANG_SERVER); + while (hResult.FetchRow()) + { + DBG_SQL_Response("hResult.FetchRow()") + iAccountID = hResult.FetchInt(0); + hResult.FetchString(1, SZF(szName)); + hResult.FetchString(2, SZF(szGroup)); + + DBG_SQL_Response("hResult.FetchInt(0) = %d", iAccountID) + DBG_SQL_Response("hResult.FetchString(1) = '%s'", szName) + DBG_SQL_Response("hResult.FetchString(2) = '%s'", szGroup) + + UTIL_GetSteamIDFromAccountID(iAccountID, SZF(szAuth)); + FormatEx(SZF(szTargetInfo), "%s (%s, unknown)", szName, szAuth); + + DB_RemoveVipPlayerByData( + REASON_EXPIRED, + szAdminInfo, + 0, + iAccountID, + szTargetInfo, + szGroup, + true + ); + } + } +} + +void DB_AddVipPlayer( + const int iAdmin, + const char[] szAdminInfo, + const int iTarget, + const int iTargetAccountID, + const char[] szTargetInfo, + const int iDuration, + const int iExpires, + const char[] szGroup +) +{ + DataPack hDataPack = new DataPack(); + + // Admin + hDataPack.WriteCell(iAdmin); + hDataPack.WriteString(szAdminInfo); + + // Target + hDataPack.WriteCell(GET_UID(iTarget)); + hDataPack.WriteCell(iTargetAccountID); + hDataPack.WriteString(szTargetInfo); + + // Data + hDataPack.WriteCell(iDuration); + hDataPack.WriteCell(iExpires); + hDataPack.WriteString(szGroup); + + int iLastVisit = iTarget ? GetTime() : 0; + + char szQuery[512], szName[MNL*2+1]; + if (iTarget) + { + GetClientName(iTarget, SZF(szQuery)); + g_hDatabase.Escape(szQuery, SZF(szName)); + } + else + { + strcopy(SZF(szName), "unknown"); + } + + if (GLOBAL_INFO & IS_MySQL) + { + FormatEx(SZF(szQuery), "INSERT INTO `vip_users` (`account_id`, `sid`, `expires`, `group`, `name`, `lastvisit`) VALUES (%d, %d, %d, '%s', '%s', %d) \ + ON DUPLICATE KEY UPDATE `expires` = %d, `group` = '%s';", iTargetAccountID, g_CVAR_iServerID, iExpires, szGroup, szName, iLastVisit, iExpires, szGroup); + DBG_SQL_Query(szQuery) + g_hDatabase.Query(SQL_Callback_OnVIPClientAdded, szQuery, hDataPack); + + return; + } + + FormatEx(SZF(szQuery), "INSERT OR REPLACE INTO `vip_users` (`account_id`, `name`, `expires`, `group`, `lastvisit`) VALUES (%d, '%s', %d, '%s', %d);", iTargetAccountID, szName, iExpires, szGroup, iLastVisit); + DBG_SQL_Query(szQuery) + g_hDatabase.Query(SQL_Callback_OnVIPClientAdded, szQuery, hDataPack); +} + +public void SQL_Callback_OnVIPClientAdded(Database hOwner, DBResultSet hResult, const char[] szError, DataPack hDataPack) +{ + DBG_SQL_Response("SQL_Callback_OnVIPClientAdded") + hDataPack.Reset(); + + // Admin + int iAdmin = GET_CID(hDataPack.ReadCell()); + + if (hResult == null || szError[0]) + { + delete hDataPack; + + if (iAdmin >= 0) + { + UTIL_Reply(iAdmin, "%t", "ADMIN_VIP_ADD_FAILED"); + } + + LogError("SQL_Callback_OnVIPClientAdded: %s", szError); + return; + } + + DBG_SQL_Response("hResult.AffectedRows = %d", hResult.AffectedRows) + + if (!hResult.AffectedRows) + { + delete hDataPack; + + if (iAdmin >= 0) + { + UTIL_Reply(iAdmin, "%t", "ADMIN_VIP_ADD_FAILED"); + } + return; + } + + int iTarget, iDuration, iExpires, iAccountID; + char szAdminInfo[PMP], szTargetInfo[PMP], szGroup[64]; + + hDataPack.ReadString(SZF(szAdminInfo)); + + // Target + iTarget = GET_CID(hDataPack.ReadCell()); + iAccountID = hDataPack.ReadCell(); + hDataPack.ReadString(SZF(szTargetInfo)); + + // Data + iDuration = hDataPack.ReadCell(); + iExpires = hDataPack.ReadCell(); + hDataPack.ReadString(SZF(szGroup)); + + delete hDataPack; + + Clients_OnVipPlayerAdded( + iAdmin, + szAdminInfo, + iTarget, + iAccountID, + szTargetInfo, + iDuration, + iExpires, + szGroup + ); +} + +void DB_RemoveVipPlayer( + const int iAdmin, + const char[] szAdminInfo, + const int iTarget, + const int iTargetAccountID, + const bool bNotify +) +{ + DataPack hDataPack = new DataPack(); + hDataPack.WriteCell(GET_UID(iAdmin)); + hDataPack.WriteString(szAdminInfo); + hDataPack.WriteCell(GET_UID(iTarget)); + hDataPack.WriteCell(iTargetAccountID); + hDataPack.WriteCell(bNotify); + + char szQuery[512]; + FormatEx(SZF(szQuery), "SELECT `name`, `group` FROM `vip_users` WHERE `account_id` = %d%s;", iTargetAccountID, g_szSID); + + DBG_SQL_Query(szQuery) + g_hDatabase.Query(SQL_Callback_SelectForRemoveClient, szQuery, hDataPack); +} + +public void SQL_Callback_SelectForRemoveClient(Database hOwner, DBResultSet hResult, const char[] szError, DataPack hDataPack) +{ + DBG_SQL_Response("SQL_Callback_SelectForRemoveClient") + + if (szError[0]) + { + delete hDataPack; + LogError("SQL_Callback_SelectForRemoveClient: %s", szError); + return; + } + + if (!hResult.FetchRow()) + { + delete hDataPack; + return; + } + + DBG_SQL_Response("hResult.FetchRow()") + hDataPack.Reset(); + + int iAdmin, iTarget, iTargetAccountID; + char szAdminInfo[128], szTargetInfo[128]; + + iAdmin = GET_CID(hDataPack.ReadCell()); + hDataPack.ReadString(SZF(szAdminInfo)); + iTarget = GET_CID(hDataPack.ReadCell()); + iTargetAccountID = hDataPack.ReadCell(); + bool bNotify = hDataPack.ReadCell(); + + char szGroup[64]; + hResult.FetchString(1, SZF(szGroup)); + + if (iTarget) + { + UTIL_GetClientInfo(iTarget, SZF(szTargetInfo)); + } + else + { + char szName[MAX_NAME_LENGTH*2+1], szAuth[32]; + UTIL_GetSteamIDFromAccountID(iTargetAccountID, SZF(szAuth)); + hResult.FetchString(0, SZF(szName)); + FormatEx(SZF(szTargetInfo), "%s (%s, unknown)", szName, szAuth); + } + + DB_RemoveVipPlayerByData( + iAdmin, + szAdminInfo, + iTarget, + iTargetAccountID, + szTargetInfo, + szGroup, + bNotify + ); +} + +void DB_RemoveVipPlayerByData( + const int iAdmin, + const char[] szAdminInfo, + const int iTarget, + const int iTargetAccountID, + const char[] szTargetInfo, + const char[] szGroup, + const bool bNotify +) +{ + DataPack hDataPack = new DataPack(); + + // Admin + hDataPack.WriteCell(GET_UID(iAdmin)); + hDataPack.WriteString(szAdminInfo); + + // Target + hDataPack.WriteCell(GET_UID(iTarget)); + hDataPack.WriteCell(iTargetAccountID); + hDataPack.WriteString(szTargetInfo); + + // Data + hDataPack.WriteString(szGroup); + hDataPack.WriteCell(bNotify); + + char szQuery[PMP]; + FormatEx(SZF(szQuery), "DELETE FROM `vip_users` WHERE `account_id` = %d%s;", iTargetAccountID, g_szSID); + + DBG_SQL_Query(szQuery) + g_hDatabase.Query(SQL_Callback_RemoveClient, szQuery, hDataPack); +} + +public void SQL_Callback_RemoveClient(Database hOwner, DBResultSet hResult, const char[] szError, DataPack hDataPack) +{ + DBG_SQL_Response("SQL_Callback_SelectRemoveClient") + + if (szError[0]) + { + delete hDataPack; + LogError("SQL_Callback_RemoveClient: %s", szError); + return; + } + + DBG_SQL_Response("hResult.AffectedRows = %d", hResult.AffectedRows) + + if (!hResult.AffectedRows) + { + delete hDataPack; + return; + } + hDataPack.Reset(); + + + int iAdmin, iTarget, iAccountID; + char szAdminInfo[PMP], szTargetInfo[PMP], szGroup[64]; + + // Admin + iAdmin = GET_CID(hDataPack.ReadCell()); + hDataPack.ReadString(SZF(szAdminInfo)); + + // Target + iTarget = GET_CID(hDataPack.ReadCell()); + iAccountID = hDataPack.ReadCell(); + hDataPack.ReadString(SZF(szTargetInfo)); + + // Data + hDataPack.ReadString(SZF(szGroup)); + bool bNotify = hDataPack.ReadCell(); + + delete hDataPack; + + if (!iTarget) + { + iTarget = UTIL_GetVipClientByAccountID(iAccountID); + } + + Clients_OnVipPlayerRemoved( + iAdmin, + szAdminInfo, + iTarget, + iAccountID, + szTargetInfo, + szGroup, + bNotify + ); +} +/** void DB_RemoveClientFromID(int iAdmin = 0, int iClient = 0, int iClientID = 0, @@ -195,12 +554,12 @@ void DB_RemoveClientFromID(int iAdmin = 0, const char[] szByWho = NULL_STRING) { DebugMessage("DB_RemoveClientFromID %N (%d): - > iClientID: %d, : bNotify: %b", iClient, iClient, iClientID, bNotify) - char szQuery[256], szName[MNL], szGroup[64]; + char szQuery[PMP], szName[MNL], szGroup[64]; DataPack hDataPack = new DataPack(); - if(iClient) + if (iClient) { - if(szSourceName[0]) + if (szSourceName[0]) { strcopy(SZF(szName), szSourceName); } @@ -209,15 +568,15 @@ void DB_RemoveClientFromID(int iAdmin = 0, GetClientName(iClient, SZF(szName)); } - if(szSourceGroup[0]) + if (szSourceGroup[0]) { strcopy(SZF(szGroup), szSourceGroup); } - else if(g_hFeatures[iClient]) + else if (g_hFeatures[iClient]) { g_hFeatures[iClient].GetString(KEY_GROUP, SZF(szGroup)); - if(!iClientID) + if (!iClientID) { g_hFeatures[iClient].GetValue(KEY_CID, iClientID); } @@ -256,7 +615,7 @@ void DB_RemoveClientFromID(int iAdmin = 0, hDataPack.WriteString(szAdmin); - if(szName[0] && szGroup[0]) + if (szName[0] && szGroup[0]) { hDataPack.WriteString(szName); hDataPack.WriteString(szGroup); @@ -270,56 +629,56 @@ void DB_RemoveClientFromID(int iAdmin = 0, g_hDatabase.Query(SQL_Callback_SelectRemoveClient, szQuery, hDataPack); } -public void SQL_Callback_SelectRemoveClient(Database hOwner, DBResultSet hResult, const char[] szError, DataPack hPack) +public void SQL_Callback_SelectRemoveClient(Database hOwner, DBResultSet hResult, const char[] szError, DataPack hDataPack) { DBG_SQL_Response("SQL_Callback_SelectRemoveClient") if (szError[0]) { - delete hPack; + delete hDataPack; LogError("SQL_Callback_SelectRemoveClient: %s", szError); return; } if (!hResult.FetchRow()) { - delete hPack; + delete hDataPack; return; } DBG_SQL_Response("hResult.FetchRow()") - hPack.Reset(); - int iClientID = hPack.ReadCell(); - hPack.ReadCell(); - hPack.ReadCell(); + hDataPack.Reset(); + int iClientID = hDataPack.ReadCell(); + hDataPack.ReadCell(); + hDataPack.ReadCell(); char szName[MAX_NAME_LENGTH*2+1]; - hPack.ReadString(SZF(szName)); + hDataPack.ReadString(SZF(szName)); hResult.FetchString(0, SZF(szName)); DBG_SQL_Response("hResult.FetchString(0) = '%s", szName) - hPack.WriteString(szName); + hDataPack.WriteString(szName); hResult.FetchString(1, SZF(szName)); DBG_SQL_Response("hResult.FetchString(1) = '%s", szName) - hPack.WriteString(szName); + hDataPack.WriteString(szName); - DB_RemoveClient(hPack, iClientID); + DB_RemoveClient(hDataPack, iClientID); } -void DB_RemoveClient(DataPack hDataPack, int iClientID) +void DB_RemoveClient(int iClientID, DataPack hDataPack) { - char szQuery[256]; + char szQuery[PMP]; FormatEx(SZF(szQuery), "DELETE FROM `vip_users` WHERE `account_id` = %d%s;", iClientID, g_szSID); DBG_SQL_Query(szQuery) g_hDatabase.Query(SQL_Callback_RemoveClient, szQuery, hDataPack); } -public void SQL_Callback_RemoveClient(Database hOwner, DBResultSet hResult, const char[] szError, DataPack hPack) +public void SQL_Callback_RemoveClient(Database hOwner, DBResultSet hResult, const char[] szError, DataPack hDataPack) { DBG_SQL_Response("SQL_Callback_SelectRemoveClient") if (szError[0]) { - delete hPack; + delete hDataPack; LogError("SQL_Callback_RemoveClient: %s", szError); return; } @@ -328,62 +687,27 @@ public void SQL_Callback_RemoveClient(Database hOwner, DBResultSet hResult, cons if (!hResult.AffectedRows) { - delete hPack; + delete hDataPack; return; } - hPack.Reset(); + hDataPack.Reset(); - int iClientID = hPack.ReadCell(); - int iAdmin = GET_CID(hPack.ReadCell()); - bool bNotify = view_as(hPack.ReadCell()); + int iClientID = hDataPack.ReadCell(); + int iAdmin = GET_CID(hDataPack.ReadCell()); + bool bNotify = view_as(hDataPack.ReadCell()); char szAdmin[128], szName[MNL], szGroup[64]; - hPack.ReadString(SZF(szAdmin)); - hPack.ReadString(SZF(szName)); - hPack.ReadString(SZF(szGroup)); - delete hPack; - - if(iAdmin == -1) - { - return; - } - - if (g_CVAR_bLogsEnable) - { - LogToFile(g_szLogFile, "%T", "LOG_VIP_DELETED", LANG_SERVER, szName, iClientID, szGroup, szAdmin); - } - - if (bNotify && iAdmin > 0) - { - ReplyToCommand(iAdmin, "%t", "ADMIN_VIP_PLAYER_DELETED", szName, iClientID); - } -} - -public void SQL_Callback_SelectExpiredAndOutdated(Database hOwner, DBResultSet hResult, const char[] szError, int iReason) -{ - DBG_SQL_Response("SQL_Callback_SelectExpiredAndOutdated") - - if (szError[0]) - { - LogError("SQL_Callback_SelectExpiredAndOutdated: %s", szError); - return; - } - - DBG_SQL_Response("hResult.RowCount = %d", hResult.RowCount) - - if (hResult.RowCount) - { - int iClientID; - char szName[MNL*2], szGroup[64]; - while (hResult.FetchRow()) - { - DBG_SQL_Response("hResult.FetchRow()") - iClientID = hResult.FetchInt(0); - DBG_SQL_Response("hResult.FetchInt(0) = %d", iClientID) - hResult.FetchString(1, SZF(szName)); - DBG_SQL_Response("hResult.FetchString(1) = '%s'", szName) - hResult.FetchString(2, SZF(szGroup)); - DBG_SQL_Response("hResult.FetchString(2) = '%s'", szGroup) - DB_RemoveClientFromID(iReason, _, iClientID, false, szName, szGroup); - } - } + hDataPack.ReadString(SZF(szAdmin)); + hDataPack.ReadString(SZF(szName)); + hDataPack.ReadString(SZF(szGroup)); + delete hDataPack; + + Clients_OnVipPlayerRemoved( + iAdmin, + szAdminInfo, + iTarget, + iTargetAccountID, + szTargetInfo, + szGroup + ); } +*/ \ No newline at end of file diff --git a/addons/sourcemod/scripting/vip/Debugger.sp b/addons/sourcemod/scripting/vip/Debugger.sp index 433b082..8e9edef 100644 --- a/addons/sourcemod/scripting/vip/Debugger.sp +++ b/addons/sourcemod/scripting/vip/Debugger.sp @@ -12,12 +12,13 @@ void DebugMsg(const char[] sMsg, any ...) // Детальность логов // #define LOG_DOWNLOADS // SQL Запросы -#define LOG_QUERIES // SQL Запросы -#define LOG_RESPONSE // Ответы SQL запросов -// #define LOG_API // API -// #define LOG_FEATURES // API -// #define LOG_CLIENTS // API -// #define LOG_DB // API +// #define LOG_QUERIES // SQL Запросы +// #define LOG_RESPONSE // Ответы SQL запросов +// #define LOG_API // API +// #define LOG_FEATURES // API +#define LOG_CLIENTS // API +// #define LOG_DB // API +#define LOG_STORAGE #else #define DebugMessage(%0) @@ -46,3 +47,23 @@ void DebugMsg(const char[] sMsg, any ...) #else #define DBG_API(%0) #endif + +#if defined LOG_FEATURES +#define DBG_FEATURES(%0) DebugMsg("FEATURES: " ... %0); +#else +#define DBG_FEATURES(%0) +#endif + + +#if defined LOG_STORAGE +#define DBG_STORAGE(%0) DebugMsg("STORAGE: " ... %0); +#else +#define DBG_STORAGE(%0) +#endif + + +#if defined LOG_CLIENTS +#define DBG_CLIENTS(%0) DebugMsg("STORAGE: " ... %0); +#else +#define DBG_CLIENTS(%0) +#endif diff --git a/addons/sourcemod/scripting/vip/Downloads.sp b/addons/sourcemod/scripting/vip/Downloads.sp index 5c30e9a..01d4638 100644 --- a/addons/sourcemod/scripting/vip/Downloads.sp +++ b/addons/sourcemod/scripting/vip/Downloads.sp @@ -6,73 +6,86 @@ void ReadDownloads() BuildPath(Path_SM, SZF(szBuffer), "data/vip/modules/downloadlist.txt"); File hFile = OpenFile(szBuffer, "r"); - if(hFile != null) + if (hFile == null) { - DBG_Download("OpenFile('%s')", szBuffer) - int iEndPos; - while (!hFile.EndOfFile() && hFile.ReadLine(SZF(szBuffer))) + return; + } + DBG_Download("OpenFile('%s')", szBuffer) + int iEndPos; + while (!hFile.EndOfFile() && hFile.ReadLine(SZF(szBuffer))) + { + DBG_Download("ReadLine = '%s'", szBuffer) + if (!szBuffer[0]) { - DBG_Download("ReadLine = '%s'", szBuffer) - if(szBuffer[0]) - { - iEndPos = StrContains(szBuffer, "//"); - DBG_Download("iEndPos = %d", iEndPos) - if(iEndPos != -1) - { - szBuffer[iEndPos] = 0; - } + continue; + } + iEndPos = StrContains(szBuffer, "//"); + DBG_Download("iEndPos = %d", iEndPos) + if (iEndPos != -1) + { + szBuffer[iEndPos] = 0; + } - if(szBuffer[0] && IsCharAlpha(szBuffer[0])) - { - DBG_Download("ReadFileLine: '%s'", szBuffer) - - TrimString(szBuffer); + if (szBuffer[0] && IsCharAlpha(szBuffer[0])) + { + DBG_Download("ReadFileLine: '%s'", szBuffer) + + TrimString(szBuffer); - File_AddToDownloadsTable(szBuffer); - } - } + File_AddToDownloadsTable(szBuffer); } - - delete hFile; } + + delete hFile; } -bool File_AddToDownloadsTable(const char[] szPath) +void File_AddToDownloadsTable(const char[] szPath) { DBG_Download("File_AddToDownloadsTable: '%s'", szPath) - if(FileExists(szPath)) + if (FileExists(szPath)) { DBG_Download("File '%s' Loaded", szPath) AddFileToDownloadsTable(szPath); + return; } - else if(DirExists(szPath)) + + if (DirExists(szPath)) { Dir_AddToDownloadsTable(szPath); } } -bool Dir_AddToDownloadsTable(const char[] szPath) +void Dir_AddToDownloadsTable(const char[] szPath) { DBG_Download("Dir_AddToDownloadsTable: '%s'", szPath) - if(DirExists(szPath)) + if (!DirExists(szPath)) { - DirectoryListing hDir = OpenDirectory(szPath); - if(hDir != null) - { - char szDirEntry[PLATFORM_MAX_PATH]; - while (hDir.GetNext(SZF(szDirEntry))) - { - if ((UTIL_StrCmpEx(szDirEntry, ".") || UTIL_StrCmpEx(szDirEntry, "..") || UTIL_StrCmpEx(szDirEntry[strlen(szDirEntry)-4], ".bz2")) == false) - { - Format(SZF(szDirEntry), "%s/%s", szPath, szDirEntry); + return; + } + + DirectoryListing hDir = OpenDirectory(szPath); + if (hDir == null) + { + return; + } - File_AddToDownloadsTable(szDirEntry); - } - } - delete hDir; + char szDirEntry[PMP]; + while (hDir.GetNext(SZF(szDirEntry))) + { + if ( + UTIL_StrCmpEx(szDirEntry, ".") || + UTIL_StrCmpEx(szDirEntry, "..") || + UTIL_StrCmpEx(szDirEntry[strlen(szDirEntry)-4], ".bz2"))) + { + continue; } + + Format(SZF(szDirEntry), "%s/%s", szPath, szDirEntry); + File_AddToDownloadsTable(szDirEntry); } -} \ No newline at end of file + + delete hDir; +} diff --git a/addons/sourcemod/scripting/vip/Features.sp b/addons/sourcemod/scripting/vip/Features.sp index d177dd5..419c6be 100644 --- a/addons/sourcemod/scripting/vip/Features.sp +++ b/addons/sourcemod/scripting/vip/Features.sp @@ -1,97 +1,207 @@ bool IsValidFeature(const char[] szFeature) { - DebugMessage("IsValidFeature:: FindStringInArray -> %i", g_hFeaturesArray.FindString(szFeature)) + DBG_FEATURES("IsValidFeature:: FindStringInArray -> %i", g_hFeaturesArray.FindString(szFeature)) return (g_hFeaturesArray.FindString(szFeature) != -1); } void Features_TurnOffAll(int iClient) { - DebugMessage("Features_TurnOffAll %N (%i)", iClient, iClient) + DBG_FEATURES("Features_TurnOffAll %N (%i)", iClient, iClient) int iFeaturesCount = g_hFeaturesArray.Length; - if(!iFeaturesCount) + if (!iFeaturesCount) { return; } char szFeature[FEATURE_NAME_LENGTH]; VIP_ToggleState eOldStatus; - Function Function_Toggle; + Function fnToggleCallback; ArrayList hArray; - DataPack hDataPack; for(int i = 0; i < iFeaturesCount; ++i) { g_hFeaturesArray.GetString(i, SZF(szFeature)); - if(GLOBAL_TRIE.GetValue(szFeature, hArray)) + if (!GetTrieValue(GLOBAL_TRIE, szFeature, hArray)) { - if(view_as(hArray.Get(FEATURES_ITEM_TYPE)) == TOGGLABLE) - { - eOldStatus = Features_GetStatus(iClient, szFeature); - hDataPack = view_as(hArray.Get(FEATURES_MENU_CALLBACKS)); - hDataPack.Position = ITEM_SELECT; - Function_Toggle = hDataPack.ReadFunction(); - if(Function_Toggle != INVALID_FUNCTION) - { - Function_OnItemToggle(view_as(hArray.Get(FEATURES_PLUGIN)), Function_Toggle, iClient, szFeature, eOldStatus, NO_ACCESS); - } - } + continue; } + + if (view_as(hArray.Get(FEATURES_ITEM_TYPE)) != TOGGLABLE) + { + continue; + } + + fnToggleCallback = Feature_GetSelectCallback(hArray); + if (fnToggleCallback == INVALID_FUNCTION) + { + continue; + } + + eOldStatus = Features_GetStatus(iClient, szFeature); + if (eOldStatus == NO_ACCESS) + { + continue; + } + + CallForward_OnFeatureToggle(iClient, szFeature, eOldStatus, NO_ACCESS); + Function_OnItemToggle(view_as(hArray.Get(FEATURES_PLUGIN)), fnToggleCallback, iClient, szFeature, eOldStatus, NO_ACCESS); + Features_SetStatus(iClient, szFeature, NO_ACCESS); } } void Features_TurnOnAll(int iClient) { - DebugMessage("Features_TurnOnAll %N (%i)", iClient, iClient) + DBG_FEATURES("Features_TurnOnAll %N (%i)", iClient, iClient) int iFeaturesCount = g_hFeaturesArray.Length; - if(iFeaturesCount != 0) + if (!iFeaturesCount) + { + return; + } + char szFeature[FEATURE_NAME_LENGTH]; + VIP_ToggleState eStatus, eNewStatus; + Function fnToggleCallback; + ArrayList hArray; + + for(int i = 0; i < iFeaturesCount; ++i) { - char szFeature[FEATURE_NAME_LENGTH]; - VIP_ToggleState eNewStatus; - Function Function_Toggle; - ArrayList hArray; - DataPack hDataPack; + GetArrayString(g_hFeaturesArray, i, SZF(szFeature)); + if (!GetTrieValue(GLOBAL_TRIE, szFeature, hArray)) + { + continue; + } + + if (view_as(hArray.Get(FEATURES_ITEM_TYPE)) != TOGGLABLE) + { + continue; + } - for(int i = 0; i < iFeaturesCount; ++i) + fnToggleCallback = Feature_GetSelectCallback(hArray); + if (fnToggleCallback == INVALID_FUNCTION) { - GetArrayString(g_hFeaturesArray, i, SZF(szFeature)); - if(GetTrieValue(GLOBAL_TRIE, szFeature, hArray)) - { - if(view_as(hArray.Get(FEATURES_ITEM_TYPE)) == TOGGLABLE) - { - hDataPack = view_as(hArray.Get(FEATURES_MENU_CALLBACKS)); - hDataPack.Position = ITEM_SELECT; - Function_Toggle = hDataPack.ReadFunction(); - if(Function_Toggle != INVALID_FUNCTION) - { - eNewStatus = Features_GetStatus(iClient, szFeature); - if(eNewStatus != NO_ACCESS) - { - Function_OnItemToggle(view_as(hArray.Get(FEATURES_PLUGIN)), Function_Toggle, iClient, szFeature, NO_ACCESS, eNewStatus); - } - } - } - } + continue; + } + + eStatus = Features_GetStatus(iClient, szFeature); + if (eStatus == NO_ACCESS) + { + continue; + } + + eNewStatus = CallForward_OnFeatureToggle(iClient, szFeature, NO_ACCESS, eStatus); + eNewStatus = Function_OnItemToggle(view_as(hArray.Get(FEATURES_PLUGIN)), fnToggleCallback, iClient, szFeature, NO_ACCESS, eStatus); + + if (eNewStatus != eStatus) + { + Features_SetStatus(iClient, szFeature, eStatus); } } } void Features_SetStatus(int iClient, const char[] szFeature, VIP_ToggleState eStatus) { - DebugMessage("Features_SetStatus: %N (%i) -> Feature: %s, eStatus: %i", iClient, iClient, szFeature, eStatus) + DBG_FEATURES("Features_SetStatus: %N (%i) -> Feature: %s, eStatus: %i", iClient, iClient, szFeature, eStatus) SetTrieValue(g_hFeatureStatus[iClient], szFeature, eStatus); } VIP_ToggleState Features_GetStatus(const int &iClient, const char[] szFeature) { static VIP_ToggleState eStatus; - if(g_hFeatureStatus[iClient].GetValue(szFeature, eStatus)) + if (g_hFeatureStatus[iClient].GetValue(szFeature, eStatus)) { - DebugMessage("Features_GetStatus: %N (%i) -> Feature: %s, eStatus: %i", iClient, iClient, szFeature, eStatus) + DBG_FEATURES("Features_GetStatus: %N (%i) -> Feature: %s, eStatus: %i", iClient, iClient, szFeature, eStatus) return eStatus; } - - DebugMessage("Features_GetStatus: %N (%i) -> Feature: %s, eStatus: %i", iClient, iClient, szFeature, NO_ACCESS) + + DBG_FEATURES("Features_GetStatus: %N (%i) -> Feature: %s, eStatus: %i", iClient, iClient, szFeature, NO_ACCESS) return NO_ACCESS; -} \ No newline at end of file +} + + +#if USE_CLIENTPREFS == 0 +void Features_GetStorageKeyName(const char[] szFeature, char[] szValue, int iMaxLength) +{ + FormatEx(szValue, iMaxLength, "FeatureStatus-%s", szFeature); +} +#endif + +#if USE_CLIENTPREFS 1 +void Features_GetValueFromStorage(int iClient, const char[] szFeature, char[] szValue, int iMaxLength) +{ + DBG_FEATURES("Features_GetValueFromStorage %N (%d): '%s'", iClient, iClient, szFeature) + + ArrayList hArray; + GetTrieValue(GLOBAL_TRIE, szFeature, hArray); + Handle hCookie = view_as(hArray.Get(FEATURES_COOKIE)); + GetClientCookie(iClient, hCookie, szValue, iMaxLength); + +} +#else +void Features_GetValueFromStorage(int iClient, const char[] szFeature, char[] szValue, int iMaxLength) +{ + DBG_FEATURES("Features_GetValueFromStorage %N (%d): '%s'", iClient, iClient, szFeature) + char szKey[128]; + Features_GetStorageKeyName(szFeature, SZF(szKey)); + Storage_GetClientValue(iClient, szKey, szValue, iMaxLength); +} +#endif + +#if USE_CLIENTPREFS 1 +void Features_SetValueToStorage(int iClient, const char[] szFeature, const char[] szValue) +{ + DBG_FEATURES("Features_SetValueToStorage %N (%d): '%s' -> '%s'", iClient, iClient, szFeature, szValue) + + ArrayList hArray; + GetTrieValue(GLOBAL_TRIE, szFeature, hArray); + Handle hCookie = view_as(hArray.Get(FEATURES_COOKIE)); + SetClientCookie(iClient, hCookie, szValue); +} +#else +void Features_SetValueToStorage(int iClient, const char[] szFeature, const char[] szValue) +{ + DBG_FEATURES("Features_SetValueToStorage %L: '%s' -> '%s'", iClient, szFeature, szValue) + char szKey[128]; + Features_GetStorageKeyName(szFeature, SZF(szKey)); + Storage_SetClientValue(iClient, szKey, szValue); +} +#endif + + +void Features_SetStatusToStorage(int iClient, const char[] szFeature, VIP_ToggleState eStatus) +{ + DBG_FEATURES("Features_SetStatusToStorage %L: '%s' -> %d", iClient, szFeature, eStatus) + char szValue[4]; + IntToString(view_as(eStatus), SZF(szValue)); + Features_SetValueToStorage(iClient, szFeature, szValue); +} + +VIP_ToggleState Features_GetStatusFromStorage(int iClient, const char[] szFeature, ArrayList hArray) +{ + char szValue[4]; + Features_GetValueFromStorage(iClient, szFeature, SZF(szValue)); + + DBG_FEATURES("Features_GetStatusFromStorage %L: '%s' -> '%s'", iClient, szFeature, szValue) + VIP_ToggleState eStatus = view_as(StringToInt(szValue)); + if (szValue[0] == '\0' || (view_as(eStatus) > 2 || view_as(eStatus) < 0)) + { + switch(hArray.Get(FEATURES_DEF_STATUS)) + { + case NO_ACCESS: eStatus = g_CVAR_bDefaultStatus ? ENABLED:DISABLED; + case ENABLED: eStatus = ENABLED; + case DISABLED: eStatus = DISABLED; + } + } + DBG_FEATURES("Features_GetStatusFromStorage %L: '%s' -> %d", iClient, szFeature, eStatus) + + return eStatus; +} + + +Function Feature_GetSelectCallback(ArrayList hFeature) +{ + DataPack hDataPack = view_as(hFeature.Get(FEATURES_MENU_CALLBACKS)); + hDataPack.Position = ITEM_SELECT; + return hDataPack.ReadFunction(); +} + diff --git a/addons/sourcemod/scripting/vip/Global.sp b/addons/sourcemod/scripting/vip/Global.sp index 527f9bd..ff70599 100644 --- a/addons/sourcemod/scripting/vip/Global.sp +++ b/addons/sourcemod/scripting/vip/Global.sp @@ -20,17 +20,21 @@ #define SET_BIT(%0,%1) %0 |= %1 #define UNSET_BIT(%0,%1) %0 &= ~%1 -#define IS_VIP (1<<0) // VIP ли игрок -#define IS_LOADED (1<<1) // Загружен ли игрок -#define IS_WAIT_CHAT_PASS (1<<2) // Ожидается ввод пароля в чат -#define IS_WAIT_CHAT_SEARCH (1<<3) // Ожидается ввод значения для поиска в чат -#define IS_SPAWNED (1<<4) // Игрок возродился -#define IS_MENU_OPEN (1<<5) // VIP-меню открыто +#define IS_VIP (1<<0) // VIP ли игрок +#define IS_LOADED (1<<1) // Загружен ли игрок +#define IS_WAIT_CHAT_PASS (1<<2) // Ожидается ввод пароля в чат +#define IS_WAIT_CHAT_SEARCH (1<<3) // Ожидается ввод значения для поиска в чат +#define IS_SPAWNED (1<<4) // Игрок возродился +#define IS_MENU_OPEN (1<<5) // VIP-меню открыто + +#define IS_CLIENT_VIP(%0) (g_iClientInfo[%0] & IS_VIP == IS_VIP) +#define IS_CLIENT_LOADED(%0) (g_iClientInfo[%0] & IS_LOADED == IS_LOADED) #define IS_STARTED (1<<0) #define IS_MySQL (1<<1) #define IS_LOADING (1<<2) +#define REASON_SERVER 0 #define REASON_PLUGIN -1 #define REASON_EXPIRED -2 #define REASON_OUTDATED -3 @@ -52,6 +56,8 @@ enum FEATURES_COOKIE, FEATURES_MENU_CALLBACKS, FEATURES_DEF_STATUS + // TODO + // FEATURES_STORAGE_KEY, } DataPackPos ITEM_SELECT = view_as(0); @@ -94,6 +100,7 @@ ArrayList g_hSortArray; StringMap g_hFeatures[MAXPLAYERS+1]; StringMap g_hFeatureStatus[MAXPLAYERS+1]; +StringMap g_hCache[MAXPLAYERS+1]; StringMap g_hClientData[MAXPLAYERS+1]; @@ -111,15 +118,9 @@ int g_CVAR_iDeleteExpired; int g_CVAR_iOutdatedExpired; float g_CVAR_fSpawnDelay; bool g_CVAR_bAutoOpenMenu; -/* -#if USE_ADMINMENU 1 -bool g_CVAR_bAddItemToAdminMenu; -#endif -*/ bool g_CVAR_bUpdateName; bool g_CVAR_bHideNoAccessItems; bool g_CVAR_bDefaultStatus; -bool g_CVAR_bLogsEnable; EngineVersion g_EngineVersion; bool g_bIsTranslationPhraseExistsAvailable; diff --git a/addons/sourcemod/scripting/vip/Info.sp b/addons/sourcemod/scripting/vip/Info.sp index 32abd59..f906a45 100644 --- a/addons/sourcemod/scripting/vip/Info.sp +++ b/addons/sourcemod/scripting/vip/Info.sp @@ -71,7 +71,7 @@ void DisplayInfo(int iClient, const char[] szEvent, const char[] szType, char[] { if (!g_hInfo.GotoFirstSubKey()) { - if(hKeyValues != g_hInfo) + if (hKeyValues != g_hInfo) { delete hKeyValues; } @@ -143,7 +143,7 @@ void DisplayInfo(int iClient, const char[] szEvent, const char[] szType, char[] } } - if(hKeyValues != g_hInfo) + if (hKeyValues != g_hInfo) { delete hKeyValues; } @@ -195,5 +195,5 @@ void ReplaceValues(int iClient, char[] szBuffer, int iBufLen, bool bExt) public int SelectInfoPanel(Menu hPanel, MenuAction action, int iClient, int iOption) { - + return 0; } diff --git a/addons/sourcemod/scripting/vip/Storage.sp b/addons/sourcemod/scripting/vip/Storage.sp new file mode 100644 index 0000000..fae77b6 --- /dev/null +++ b/addons/sourcemod/scripting/vip/Storage.sp @@ -0,0 +1,165 @@ + +#define IS_CLIENT_CACHE_LOADED(%0) g_bIsCacheLoaded[%0] + +static bool g_bIsCacheLoaded[MPL+1]; + +bool Storage_IsClientLoaded(int iClient) +{ + DBG_STORAGE("Storage_IsClientLoaded: %N (%d): %b", iClient, iClient, IS_CLIENT_CACHE_LOADED(iClient) && g_hCache[iClient]) + return IS_CLIENT_CACHE_LOADED(iClient) && g_hCache[iClient]; +} + +void Storage_SetClientValue(int iClient, const char[] szKey, const char[] szValue) +{ + if (Storage_IsClientLoaded(iClient)) + { + g_hCache[iClient].SetString(szKey, szValue); + } +} + +void Storage_GetClientValue(int iClient, const char[] szKey, char[] szValue, int iMaxLength) +{ + if (Storage_IsClientLoaded(iClient)) + { + g_hCache[iClient].GetString(szKey, szValue, iMaxLength); + } +} + +void Storage_LoadClient(int iClient) +{ + char szQuery[PMP]; + + int iAccountID = GetSteamAccountID(iClient); + DBG_STORAGE("Storage_LoadClient: %N (%d): %d", iClient, iClient, iAccountID) + + FormatEx(SZF(szQuery), "SELECT `key`, `value` \ + FROM `vip_storage` \ + WHERE `account_id` = %d%s;", + iAccountID, g_szSID); + + DBG_SQL_Query(szQuery) + g_hDatabase.Query(SQL_Callback_OnClientLoadStorage, szQuery, UID(iClient)); +} + +public void SQL_Callback_OnClientLoadStorage(Database hOwner, DBResultSet hResult, const char[] szError, any iUserID) +{ + DBG_SQL_Response("SQL_Callback_OnClientLoadStorage") + if (hResult == null || szError[0]) + { + LogError("SQL_Callback_OnClientLoadStorage: %s", szError); + return; + } + + int iClient = CID(iUserID); + if (!iClient || !IsClientInGame(iClient)) + { + return; + } + + g_hCache[iClient] = new StringMap(); + + DBG_STORAGE("SQL_Callback_OnClientLoadStorage: %N (%d)", iClient, iClient) + DBG_STORAGE("RowCount: %d", hResult.RowCount) + if (!hResult.RowCount) + { + Storage_OnClientLoaded(iClient); + return; + } + + char szKey[128], szValue[PMP]; + + while (hResult.FetchRow()) + { + hResult.FetchString(0, SZF(szKey)); + hResult.FetchString(1, SZF(szValue)); + DBG_STORAGE("SetString: '%s' -> '%s'", szKey, szValue) + + g_hCache[iClient].SetString(szKey, szValue); + } + + Storage_OnClientLoaded(iClient); +} + +void Storage_OnClientLoaded(int iClient) +{ + DBG_STORAGE("Storage_OnClientLoaded: %N (%d)", iClient, iClient) + g_bIsCacheLoaded[iClient] = true; + + CallForward_OnClientStorageLoaded(iClient); +} + +void Storage_ResetClient(int iClient) +{ + DBG_STORAGE("Storage_ResetClient: %N (%d)", iClient, iClient) + + if (g_hCache[iClient]) + { + delete g_hCache[iClient]; + g_hCache[iClient] = null; + } + + g_bIsCacheLoaded[iClient] = false; +} + +void Storage_SaveClient(int iClient) +{ + DBG_STORAGE("Storage_SaveClient: %N (%d)", iClient, iClient) + + if (!Storage_IsClientLoaded(iClient) || !g_hCache[iClient]) + { + return; + } + int iAccountID = GetSteamAccountID(iClient); + int iUpdated = GetTime(); + + StringMapSnapshot hStorageSnapshot = g_hCache[iClient].Snapshot(); + + char szKey[128], szValue[PMP]; + + for(int i = 0, iSize = hStorageSnapshot.Length; i < iSize; ++i) + { + hStorageSnapshot.GetKey(i, SZF(szKey)); + g_hCache[iClient].GetString(szKey, SZF(szValue)); + DBG_STORAGE("GetString: '%s' -> '%s'", szKey, szValue) + + + Storage_SaveClientValue(iAccountID, szKey, szValue, iUpdated); + } + + delete hStorageSnapshot; +} + +void Storage_SaveClientValue(int iAccountID, const char[] szKey, const char[] szValue, int iUpdated) +{ + char szQuery[512]; + if (GLOBAL_INFO & IS_MySQL) + { + g_hDatabase.Format(SZF(szQuery), "INSERT INTO `vip_storage` (`account_id`, `sid`, `key`, `value`, `updated`) \ + VALUES (%d, %d, \"%s\", \"%s\", %d) \ + ON DUPLICATE KEY UPDATE \ + `value` = \"%s\", `updated` = %d;", + iAccountID, g_CVAR_iServerID, szKey, szValue, iUpdated, szValue, iUpdated); + } + else + { + g_hDatabase.Format(SZF(szQuery), "INSERT OR REPLACE INTO `vip_storage` (`account_id`, `key`, `value`, `updated`) \ + VALUES (%d, \"%s\", \"%s\", %d);", + iAccountID, szKey, szValue, iUpdated); + } + + DBG_SQL_Query(szQuery) + g_hDatabase.Query(SQL_Callback_OnClientSaveStorage, szQuery); +} + +public void SQL_Callback_OnClientSaveStorage(Database hOwner, DBResultSet hResult, const char[] szError, any iData) +{ + DBG_SQL_Response("SQL_Callback_OnClientSaveStorage") + if (hResult == null || szError[0]) + { + LogError("SQL_Callback_OnClientSaveStorage: %s", szError); + return; + } +} + +// TODO: add clear outdated + diff --git a/addons/sourcemod/scripting/vip/UTIL.sp b/addons/sourcemod/scripting/vip/UTIL.sp index e684838..0b182d7 100644 --- a/addons/sourcemod/scripting/vip/UTIL.sp +++ b/addons/sourcemod/scripting/vip/UTIL.sp @@ -222,7 +222,6 @@ void UTIL_GetSteamIDFromAccountID(int iAccountID, char[] szSteamID, int iMaxLen) iAccountID -= iPart; FormatEx(szSteamID, iMaxLen, "STEAM_%d:%d:%d", g_EngineVersion == Engine_CSGO ? 1:0, iPart, iAccountID/2); } - } } @@ -230,48 +229,12 @@ void UTIL_GetClientInfo(int iClient, char[] szBuffer, int iMaxLen) { char szName[MNL], szAuth[32], szIP[24]; GetClientName(iClient, SZF(szName)); - GetClientAuthId(iClient, AuthId_Steam2, SZF(szAuth)); + GetClientAuthId(iClient, AuthId_Engine, SZF(szAuth)); GetClientIP(iClient, SZF(szIP)); - FormatEx(szBuffer, iMaxLen, "%s (%s, %s)", szName, szAuth, szIP); + FormatEx(szBuffer, iMaxLen, "%s <%s, %s>", szName, szAuth, szIP); } -void UTIL_ReloadVIPPlayers(int iClient, bool bNotify) -{ - for (int i = 1; i <= MaxClients; ++i) - { - if (IsClientInGame(i)) - { - Clients_CheckVipAccess(i, false, true); - } - } - - if (bNotify) - { - UTIL_Reply(iClient, "%t", "VIP_CACHE_REFRESHED"); - } -} -/* -void UTIL_REM_VIP_PLAYER(int iClient = OWNER_SERVER, int iTarget = 0, int iAccID = 0, int iClientID, const char[] szReason) -{ - if (g_CVAR_bLogsEnable) - { - if(iTarget) - { - LogToFile(g_szLogFile, "%T", "REMOVING_PLAYER", LANG_SERVER, iTarget); - } - } - - DB_RemoveClientFromID(iClient, iClientID, false); - - ResetClient(iTarget); - - CallForward_OnVIPClientRemoved(iTarget, szReason); - - DisplayClientInfo(iTarget, "expired_info"); -} -*/ - void UTIL_Reply(int iClient, const char[] szMsg, any ...) { if(iClient < 0) @@ -293,180 +256,12 @@ void UTIL_Reply(int iClient, const char[] szMsg, any ...) } } -void UTIL_ADD_VIP_PLAYER(int iAdmin = OWNER_SERVER, - int iTarget = 0, - int iAccID = 0, - int iDuration, - const char[] szGroup, - const char[] szByWho = NULL_STRING) +int UTIL_GetVipClientByAccountID(int iAccountID) { - char szQuery[PMP*2], szName[MNL*2+1]; - char szAdmin[PMP], szTargetInfo[PMP]; - int iExpires, iAccountID; - - if (iDuration) - { - iExpires = iDuration + GetTime(); - } - else - { - iExpires = iDuration; - } - - if (iTarget) - { - GetClientName(iTarget, SZF(szQuery)); - g_hDatabase.Escape(szQuery, SZF(szName)); - iAccountID = GetSteamAccountID(iTarget); - UTIL_GetClientInfo(iTarget, SZF(szTargetInfo)); - } - else - { - strcopy(SZF(szName), "unknown"); - iAccountID = iAccID; - UTIL_GetSteamIDFromAccountID(iAccountID, SZF(szQuery)); - FormatEx(SZF(szTargetInfo), "unknown (%s, unknown)", szQuery); - } - - DataPack hDataPack = new DataPack(); - - // Admin - - switch(iAdmin) - { - case OWNER_PLUGIN: - { - FormatEx(SZF(szAdmin), "%T %s", "BY_PLUGIN", LANG_SERVER, szByWho); - } - case OWNER_SERVER: - { - FormatEx(SZF(szAdmin), "%T", "BY_SERVER", LANG_SERVER); - } - default: - { - char szAdminInfo[128]; - UTIL_GetClientInfo(iAdmin, SZF(szAdminInfo)); - FormatEx(SZF(szAdmin), "%T %s", "BY_ADMIN", LANG_SERVER, szAdminInfo); - iAdmin = UID(iAdmin); - } - } - hDataPack.WriteCell(iAdmin); - hDataPack.WriteString(szAdmin); - - // Target - hDataPack.WriteCell(GET_UID(iTarget)); - hDataPack.WriteCell(iAccountID); - hDataPack.WriteString(szTargetInfo); - - // Data - hDataPack.WriteCell(iDuration); - hDataPack.WriteCell(iExpires); - hDataPack.WriteString(szGroup); - - int iLastVisit = iTarget ? GetTime():0; - - if (GLOBAL_INFO & IS_MySQL) + int iClientID; + for (int i = 1; i <= MaxClients; ++i) { - FormatEx(SZF(szQuery), "INSERT INTO `vip_users` (`account_id`, `sid`, `expires`, `group`, `name`, `lastvisit`) VALUES (%d, %d, %d, '%s', '%s', %d) \ - ON DUPLICATE KEY UPDATE `expires` = %d, `group` = '%s';", iAccountID, g_CVAR_iServerID, iExpires, szGroup, szName, iLastVisit, iExpires, szGroup); - DBG_SQL_Query(szQuery) - g_hDatabase.Query(SQL_Callback_OnVIPClientAdded, szQuery, hDataPack); - - return; + if (IsClientInGame(i) && g_hFeatures[i] != null && g_hFeatures[i].GetValue(KEY_CID, iClientID) && iClientID == iAccountID) return i; } - - FormatEx(SZF(szQuery), "INSERT OR REPLACE INTO `vip_users` (`account_id`, `name`, `expires`, `group`, `lastvisit`) VALUES (%d, '%s', %d, '%s', %d);", iAccountID, szName, iExpires, szGroup, iLastVisit); - DBG_SQL_Query(szQuery) - g_hDatabase.Query(SQL_Callback_OnVIPClientAdded, szQuery, hDataPack); + return 0; } - -public void SQL_Callback_OnVIPClientAdded(Database hOwner, DBResultSet hResult, const char[] szError, any hPack) -{ - DBG_SQL_Response("SQL_Callback_OnVIPClientAdded") - DataPack hDataPack = view_as(hPack); - hDataPack.Reset(); - - // Admin - int iAdmin = GET_CID(hDataPack.ReadCell()); - - if (hResult == null || szError[0]) - { - delete hDataPack; - - if (iAdmin >= 0) - { - UTIL_Reply(iAdmin, "%t", "ADMIN_VIP_ADD_FAILED"); - } - - LogError("SQL_Callback_OnVIPClientAdded: %s", szError); - return; - } - - DBG_SQL_Response("hResult.AffectedRows = %d", hResult.AffectedRows) - - if (!hResult.AffectedRows) - { - delete hDataPack; - - if (iAdmin >= 0) - { - UTIL_Reply(iAdmin, "%t", "ADMIN_VIP_ADD_FAILED"); - } - return; - } - - int iTarget, iDuration, iExpires, iAccountID; - char szAdmin[PMP], szTargetInfo[PMP], szExpires[64], szDuration[64], szGroup[64]; - - hDataPack.ReadString(SZF(szAdmin)); - - // Target - iTarget = GET_CID(hDataPack.ReadCell()); - iAccountID = hDataPack.ReadCell(); - hDataPack.ReadString(SZF(szTargetInfo)); - - // Data - iDuration = hDataPack.ReadCell(); - iExpires = hDataPack.ReadCell(); - hDataPack.ReadString(SZF(szGroup)); - - delete hDataPack; - - if (iTarget) - { - Clients_CheckVipAccess(iTarget, true); - CallForward_OnVIPClientAdded(iTarget, iAdmin); - } - - char szAuth[32]; - I2S(iAccountID, szAuth); - - if (iAdmin >= 0) - { - if (iDuration) - { - UTIL_GetTimeFromStamp(SZF(szDuration), iDuration, iAdmin); - FormatTime(SZF(szExpires), "%d/%m/%Y - %H:%M", iExpires); - } - else - { - FormatEx(SZF(szDuration), "%T", "PERMANENT", iAdmin); - FormatEx(SZF(szExpires), "%T", "NEVER", iAdmin); - } - UTIL_Reply(iAdmin, "%t", "ADMIN_VIP_ADD_SUCCESS", szTargetInfo, iAccountID); - } - - if (g_CVAR_bLogsEnable) - { - if (iDuration) - { - UTIL_GetTimeFromStamp(SZF(szExpires), iDuration, LANG_SERVER); - } - else - { - FormatEx(SZF(szExpires), "%T", "PERMANENT", LANG_SERVER); - FormatEx(SZF(szExpires), "%T", "NEVER", LANG_SERVER); - } - LogToFile(g_szLogFile, "%T", "LOG_VIP_ADDED", LANG_SERVER, szTargetInfo, iAccountID, szDuration, szExpires, szGroup, szAdmin); - } -} \ No newline at end of file diff --git a/addons/sourcemod/scripting/vip/VipMenu.sp b/addons/sourcemod/scripting/vip/VipMenu.sp index 5f8c4e0..10aacf6 100644 --- a/addons/sourcemod/scripting/vip/VipMenu.sp +++ b/addons/sourcemod/scripting/vip/VipMenu.sp @@ -1,8 +1,6 @@ void VIPMenu_Setup() { g_hVIPMenu = new Menu(Handler_VIPMenu, MenuAction_Start | MenuAction_Display | MenuAction_Cancel | MenuAction_Select | MenuAction_DisplayItem | MenuAction_DrawItem); - - g_hVIPMenu.AddItem("NO_FEATURES", "NO_FEATURES", ITEMDRAW_DISABLED); } void AddFeatureToVIPMenu(const char[] szFeature) @@ -93,13 +91,14 @@ stock void PrintArray(ArrayList &hArray) } #endif */ + public int Handler_VIPMenu(Menu hMenu, MenuAction action, int iClient, int iOption) { - if((action == MenuAction_Display || + if ((action == MenuAction_Display || action == MenuAction_DisplayItem || action == MenuAction_DrawItem || action == MenuAction_Select) && - (!(g_iClientInfo[iClient] & IS_VIP) || !g_hFeatures[iClient])) + (!IS_CLIENT_VIP(iClient) || !g_hFeatures[iClient])) { return 0; } @@ -122,29 +121,11 @@ public int Handler_VIPMenu(Menu hMenu, MenuAction action, int iClient, int iOpti g_hFeatures[iClient].Remove(KEY_MENUITEM); DebugMessage("MenuAction_Display: Client: %i", iClient) - char szTitle[256]; - int iExp; - if (g_hFeatures[iClient].GetValue(KEY_EXPIRES, iExp) && iExp > 0) + char szTitle[PMP]; + if (FormatMenuTitle(iClient, SZF(szTitle))) { - int iTime = GetTime(); - if (iTime < iExp) - { - char szExpires[64]; - UTIL_GetTimeFromStamp(SZF(szExpires), iExp - iTime, iClient); - FormatEx(SZF(szTitle), "%T\n \n%T: %s\n \n", "VIP_MENU_TITLE", iClient, "EXPIRES_IN", iClient, szExpires); - } - else - { - Clients_ExpiredClient(iClient); - return 0; - } - } - else - { - FormatEx(SZF(szTitle), "%T\n \n", "VIP_MENU_TITLE", iClient); + (view_as(iOption)).SetTitle(szTitle); } - - (view_as(iOption)).SetTitle(szTitle); } case MenuAction_DrawItem: @@ -189,12 +170,6 @@ public int Handler_VIPMenu(Menu hMenu, MenuAction action, int iClient, int iOpti DebugMessage("MenuAction_DisplayItem: Client: %i, Feature: %s", iClient, szFeature) static char szDisplay[128]; - if (strcmp(szFeature, "NO_FEATURES") == 0) - { - FormatEx(SZF(szDisplay), "%T", "NO_FEATURES", iClient); - return RedrawMenuItem(szDisplay); - } - if (GLOBAL_TRIE.GetValue(szFeature, hBuffer)) { DataPack hDataPack = view_as(hBuffer.Get(FEATURES_MENU_CALLBACKS)); @@ -220,7 +195,7 @@ public int Handler_VIPMenu(Menu hMenu, MenuAction action, int iClient, int iOpti } } - if(IsTranslationPhraseExists(szFeature)) + if (IsTranslationPhraseExists(szFeature)) { FormatEx(SZF(szDisplay), "%T", szFeature, iClient); } @@ -253,7 +228,6 @@ public int Handler_VIPMenu(Menu hMenu, MenuAction action, int iClient, int iOpti hPlugin = view_as(hBuffer.Get(FEATURES_PLUGIN)); if (view_as(hBuffer.Get(FEATURES_ITEM_TYPE)) == TOGGLABLE) { - char szBuffer[4]; VIP_ToggleState eOldStatus, eNewStatus; eOldStatus = Features_GetStatus(iClient, szFeature); @@ -269,8 +243,7 @@ public int Handler_VIPMenu(Menu hMenu, MenuAction action, int iClient, int iOpti if (eNewStatus != eOldStatus) { Features_SetStatus(iClient, szFeature, eNewStatus); - IntToString(view_as(eNewStatus), SZF(szBuffer)); - SetClientCookie(iClient, view_as(GetArrayCell(hBuffer, FEATURES_COOKIE)), szBuffer); + Features_SetStatusToStorage(iClient, szFeature, eNewStatus); } } @@ -290,7 +263,30 @@ public int Handler_VIPMenu(Menu hMenu, MenuAction action, int iClient, int iOpti return 0; } -bool OnVipMenuFlood(int iClient) +bool FormatMenuTitle(int iClient, char[] szTitle, int iMaxLen) +{ + int iExp; + if (g_hFeatures[iClient].GetValue(KEY_EXPIRES, iExp) && iExp > 0) + { + int iTime = GetTime(); + if (iTime > iExp) + { + Clients_ExpiredClient(iClient); + return false; + } + + char szExpires[64]; + UTIL_GetTimeFromStamp(SZF(szExpires), iExp - iTime, iClient); + FormatEx(szTitle, iMaxLen, "%T\n \n%T: %s\n ", "VIP_MENU_TITLE", iClient, "EXPIRES_IN", iClient, szExpires); + return true; + } + + FormatEx(szTitle, iMaxLen, "%T\n ", "VIP_MENU_TITLE", iClient); + + return true; +} + +bool IsVipMenuFlood(int iClient) { static float fLastTime[MAXPLAYERS + 1]; if (fLastTime[iClient] > 0.0) @@ -311,3 +307,42 @@ bool IsTranslationPhraseExists(const char[] szPhrase) return true; } + +void DisplayVipMenu(int iClient) +{ + bool bResult = g_hVIPMenu.Display(iClient, MENU_TIME_FOREVER); + if (!bResult) { + DisplayEmptyFeaturesMenu(iClient); + } +} + +void DisplayEmptyFeaturesMenu(int iClient) +{ + char szBuffer[PMP]; + if (!FormatMenuTitle(iClient, SZF(szBuffer))) + { + return; + } + + Menu hMenu = new Menu(Handler_EmptyVIPMenu, MenuAction_End); + + hMenu.SetTitle(szBuffer); + + FormatEx(SZF(szBuffer), "%T", "NO_FEATURES", iClient); + hMenu.AddItem(NULL_STRING, szBuffer, ITEMDRAW_DISABLED); + + hMenu.Display(iClient, MENU_TIME_FOREVER); +} + +public int Handler_EmptyVIPMenu(Menu hMenu, MenuAction action, int iClient, int iOption) +{ + switch (action) + { + case MenuAction_End: + { + delete hMenu; + } + } + + return 0; +} diff --git a/addons/sourcemod/scripting/vip/adminmenu/Add.sp b/addons/sourcemod/scripting/vip/adminmenu/Add.sp index fbf1370..dceb96f 100644 --- a/addons/sourcemod/scripting/vip/adminmenu/Add.sp +++ b/addons/sourcemod/scripting/vip/adminmenu/Add.sp @@ -11,7 +11,7 @@ void ShowAddVIPMenu(int iClient) { if (IsClientInGame(i) && IsFakeClient(i) == false && GetClientName(i, SZF(szName))) { - if (g_iClientInfo[i] & IS_VIP) + if (IS_CLIENT_VIP(i)) { g_hFeatures[i].GetValue(KEY_CID, iClientID); if (iClientID != -1) @@ -43,20 +43,28 @@ public int MenuHandler_AddVip_PlayerList(Menu hMenu, MenuAction action, int iCli case MenuAction_End:delete hMenu; case MenuAction_Cancel: { - if (Item == MenuCancel_ExitBack) BackToAdminMenu(iClient); + if (Item == MenuCancel_ExitBack) + { + BackToAdminMenu(iClient); + } } case MenuAction_Select: { char szUserID[16]; hMenu.GetItem(Item, SZF(szUserID)); int UserID = StringToInt(szUserID); - if (CID(UserID)) + if (!CID(UserID)) { - g_hClientData[iClient].SetValue(DATA_KEY_TargetUID, UserID); - g_hClientData[iClient].SetValue(DATA_KEY_TimeType, TIME_SET); - g_hClientData[iClient].SetValue(DATA_KEY_MenuType, MENU_TYPE_ADD); - ShowTimeMenu(iClient); - } else VIP_PrintToChatClient(iClient, "%t", "PLAYER_NO_LONGER_AVAILABLE"); + VIP_PrintToChatClient(iClient, "%t", "PLAYER_NO_LONGER_AVAILABLE"); + return 0; + } + + g_hClientData[iClient].SetValue(DATA_KEY_TargetUID, UserID); + g_hClientData[iClient].SetValue(DATA_KEY_TimeType, TIME_SET); + g_hClientData[iClient].SetValue(DATA_KEY_MenuType, MENU_TYPE_ADD); + ShowTimeMenu(iClient); } } + + return 0; } diff --git a/addons/sourcemod/scripting/vip/adminmenu/Del.sp b/addons/sourcemod/scripting/vip/adminmenu/Del.sp index 6e6a351..f0f8582 100644 --- a/addons/sourcemod/scripting/vip/adminmenu/Del.sp +++ b/addons/sourcemod/scripting/vip/adminmenu/Del.sp @@ -1,4 +1,4 @@ -void ShowDeleteVipPlayerMenu(int iClient) +void ShowConfirmDeleteVipPlayerMenu(int iClient) { char szBuffer[128]; @@ -13,6 +13,8 @@ void ShowDeleteVipPlayerMenu(int iClient) hMenu.AddItem(NULL_STRING, szBuffer); ReductionMenu(hMenu, 4); + + // TODO: add back button hMenu.Display(iClient, MENU_TIME_FOREVER); } @@ -36,33 +38,15 @@ public int MenuHandler_DeleteVipPlayerMenu(Menu hMenu, MenuAction action, int iC g_hClientData[iClient].GetValue(DATA_KEY_TargetID, iTargetID); int iTarget = 0; - if(g_hClientData[iClient].GetValue(DATA_KEY_TargetUID, iTarget)) + if (g_hClientData[iClient].GetValue(DATA_KEY_TargetUID, iTarget)) { iTarget = CID(iTarget); - if (!iTarget && iTargetID != -1) - { - iTarget = IsClientOnline(iTargetID); - } - - if (iTarget) - { - DB_RemoveClientFromID(iClient, iTarget, _, true); - Features_TurnOffAll(iTarget); - ResetClient(iTarget); - CallForward_OnVIPClientRemoved(iTarget, "Removed by Admin", iClient); - DisplayClientInfo(iTarget, "expired_info"); - BackToAdminMenu(iClient); - return 0; - } } - - if(iTargetID != -1) + if (iTarget) { - char szGroup[64], szName[MAX_NAME_LENGTH]; - g_hClientData[iClient].GetString(DATA_KEY_Name, SZF(szName)); - g_hClientData[iClient].GetString(DATA_KEY_Group, SZF(szGroup)); - DB_RemoveClientFromID(iClient, _, iTargetID, true, szName, szGroup); + CallForward_OnVIPClientRemoved(iTarget, "Removed by Admin", iClient); } + Clients_RemoveVipPlayer(iClient, iTarget, iTargetID, true); BackToAdminMenu(iClient); } diff --git a/addons/sourcemod/scripting/vip/adminmenu/Edit.sp b/addons/sourcemod/scripting/vip/adminmenu/Edit.sp index c759d97..9e5f863 100644 --- a/addons/sourcemod/scripting/vip/adminmenu/Edit.sp +++ b/addons/sourcemod/scripting/vip/adminmenu/Edit.sp @@ -25,7 +25,7 @@ public int MenuHandler_EditTimeMenu(Menu hMenu, MenuAction action, int iClient, case MenuAction_End: delete hMenu; case MenuAction_Cancel: { - if(Item == MenuCancel_ExitBack) + if (Item == MenuCancel_ExitBack) { ShowTargetInfoMenu(iClient); } diff --git a/addons/sourcemod/scripting/vip/adminmenu/List.sp b/addons/sourcemod/scripting/vip/adminmenu/List.sp index 10d5f00..ce384c2 100644 --- a/addons/sourcemod/scripting/vip/adminmenu/List.sp +++ b/addons/sourcemod/scripting/vip/adminmenu/List.sp @@ -21,7 +21,7 @@ void ShowVipPlayersListMenu(int iClient) szUserID[0] = 0; for (i = 1; i <= MaxClients; ++i) { - if (IsClientInGame(i) && (g_iClientInfo[i] & IS_VIP) && !IsFakeClient(i) && GetClientName(i, SZF(szName))) + if (IsClientInGame(i) && IS_CLIENT_VIP(i) && !IsFakeClient(i) && GetClientName(i, SZF(szName))) { g_hFeatures[i].GetValue(KEY_CID, iClientID); FormatEx(SZF(szUserID), "u%d", UID(i)); @@ -98,7 +98,7 @@ public int MenuHandler_VipPlayersListMenu(Menu hMenu, MenuAction action, int iCl g_hFeatures[iTarget].GetValue(KEY_CID, UserID); g_hClientData[iClient].SetValue(DATA_KEY_TargetID, UserID); - if(UserID == -1) + if (UserID == -1) { ShowTemporaryTargetInfo(iClient); return 0; @@ -186,6 +186,8 @@ public int MenuHandler_SearchPlayersListMenu(Menu hMenu, MenuAction action, int } } } + + return 0; } void ShowVipPlayersFromDBMenu(int iClient, int iOffset = 0) @@ -197,10 +199,10 @@ void ShowVipPlayersFromDBMenu(int iClient, int iOffset = 0) char szQuery[1024], szSearch[64], szWhere[128]; szSearch[0] = 0; szWhere[0] = 0; - if(g_hClientData[iClient].GetString(DATA_KEY_Search, SZF(szSearch)) && szSearch[0]) + if (g_hClientData[iClient].GetString(DATA_KEY_Search, SZF(szSearch)) && szSearch[0]) { int iAccountID = UTIL_GetAccountIDFromSteamID(szSearch); - if(iAccountID) + if (iAccountID) { FormatEx(SZF(szWhere), " AND `account_id` = %d", iAccountID); } @@ -221,7 +223,7 @@ void ShowVipPlayersFromDBMenu(int iClient, int iOffset = 0) } else { - if(szWhere[0]) + if (szWhere[0]) { FormatEx(SZF(szQuery), "SELECT `account_id`, `name` \ FROM `vip_users` \ @@ -258,7 +260,7 @@ public void SQL_Callback_SelectVipPlayers(Database hOwner, DBResultSet hResult, hMenu.ExitBackButton = true; szSearch[0] = 0; g_hClientData[iClient].GetString(DATA_KEY_Search, SZF(szSearch)); - if(szSearch[0]) + if (szSearch[0]) { hMenu.SetTitle("%T:\n%T:\n ", "MENU_LIST_VIP", iClient, "MENU_SEARCH", iClient, szSearch, hResult.RowCount); } @@ -288,7 +290,7 @@ public void SQL_Callback_SelectVipPlayers(Database hOwner, DBResultSet hResult, DBG_SQL_Response("hResult.FetchInt(0) = %d", iClientID) DBG_SQL_Response("hResult.FetchString(1) = '%s", szName) - if(IsClientOnline(iClientID)) + if (UTIL_GetVipClientByAccountID(iClientID)) { Format(SZF(szName), "• %s", szName); } @@ -372,7 +374,7 @@ void ShowTemporaryTargetInfo(int iClient) int iTarget; g_hClientData[iClient].GetValue(DATA_KEY_TargetUID, iTarget); iTarget = CID(iTarget); - if(!iTarget) + if (!iTarget) { VIP_PrintToChatClient(iClient, "%t", "PLAYER_NO_LONGER_AVAILABLE"); ShowVipPlayersListMenu(iClient); @@ -423,8 +425,8 @@ void ShowTargetInfoMenu(int iClient) { FormatEx(SZF(szBuffer), "%T", "NEVER", iClient); } - - if(iClientID == -1) + + if (iClientID == -1) { Format(SZF(szBuffer), "%s (%T)", szBuffer, "TEMPORARY", iClient); } @@ -478,7 +480,7 @@ public int MenuHandler_VipClientInfoMenu(Menu hMenu, MenuAction action, int iCli { switch (Item) { - case 0: ShowDeleteVipPlayerMenu(iClient); + case 0: ShowConfirmDeleteVipPlayerMenu(iClient); case 1: ShowEditTimeMenu(iClient); case 2: { @@ -490,4 +492,6 @@ public int MenuHandler_VipClientInfoMenu(Menu hMenu, MenuAction action, int iCli } } } + + return 0; } diff --git a/addons/sourcemod/translations/vip_core.phrases.txt b/addons/sourcemod/translations/vip_core.phrases.txt index 64da0a3..848c1f3 100644 --- a/addons/sourcemod/translations/vip_core.phrases.txt +++ b/addons/sourcemod/translations/vip_core.phrases.txt @@ -134,14 +134,14 @@ } "ADMIN_VIP_ADD_SUCCESS" { - "#format" "{1:s},{2:d}" - "en" "VIP-player {1} ({2}, ID: {3}) successfully added!" - "fi" "VIP-Pelaaja {1} ({2}, ID: {3}) onnistuneesti lisätty!" - "de" "VIP-Spieler {1} ({2}, ID: {3}) erfolgreich hinzugefügt!" - "pt" "VIP adicionado {1} ({2}, ID: {3}) com sucesso!" - "pt_p" "VIP adicionado {1} ({2}, ID: {3}) com sucesso!" - "ru" "{DEFAULT}VIP-Игрок {GREEN}{1} {DEFAULT}(ID: {GREEN}{2}{DEFAULT}) успешно добавлен!" - "ua" "{DEFAULT}VIP-Гравець {GREEN}{1} {DEFAULT}(ID: {GREEN}{2}{DEFAULT}) успішно доданий!" + "#format" "{1:s},{2:s}" + "en" "{DEFAULT}VIP-player {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) successfully added!" + "fi" "{DEFAULT}VIP-Pelaaja {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) onnistuneesti lisätty!" + "de" "{DEFAULT}VIP-Spieler {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) erfolgreich hinzugefügt!" + "pt" "{DEFAULT}VIP adicionado {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) com sucesso!" + "pt_p" "{DEFAULT}VIP adicionado {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) com sucesso!" + "ru" "{DEFAULT}VIP-Игрок {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) успешно добавлен!" + "ua" "{DEFAULT}VIP-Гравець {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) успішно доданий!" } "LOG_VIP_ADDED" @@ -351,16 +351,15 @@ } "ADMIN_VIP_PLAYER_DELETED" { - "#format" "{1:s},{2:i}" - "en" "VIP-player {1} (ID: {2}) was successfully removed" - "fi" "VIP-Pelaaja {1} (ID: {2}) on onnistuneesti poistettu" - "de" "VIP-Spieler {1} (ID: {2}) wurde erfolgreich gelöscht" - "pt" "VIP do player {1} (ID: {2}) foi removido com sucesso" - "pt_p" "O VIP do jogador {1} (ID: {2}) foi removido com sucesso" - "ru" "VIP-игрок {1} (ID: {2}) успешно удален" - "ua" "VIP-гравець {1} (ID: {2}) успішно видалений" + "#format" "{1:s},{2:s}" + "en" "{DEFAULT}VIP-player {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) was successfully removed" + "fi" "{DEFAULT}VIP-Pelaaja {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) on onnistuneesti poistettu" + "de" "{DEFAULT}VIP-Spieler {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) wurde erfolgreich gelöscht" + "pt" "{DEFAULT}VIP do player {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) foi removido com sucesso" + "pt_p" "{DEFAULT}O VIP do jogador {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) foi removido com sucesso" + "ru" "{DEFAULT}VIP-игрок {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) успешно удален" + "ua" "{DEFAULT}VIP-гравець {GREEN}{1} {DEFAULT}({GREEN}{2}{DEFAULT}) успішно видалений" } - "LOG_VIP_DELETED" { "#format" "{1:s},{2:d},{3:s},{4:s}"