Заказать игровой сервер Контакты (заказать плагин/исправить ошибки/другое) Поиск

[ вход ]
[ последние сообщения ]

  • Страница 1 из 3
  • 1
  • 2
  • 3
  • »
Форум » SourceMod >> CS:Source >> CSGO » Уроки SourceMod (SourcePawn) Скриптинга » Keyvalues - База (группа) для хранения информации
Keyvalues - База (группа) для хранения информации
_wS_ Дата: Пятница, 13.01.2012, 10:36:41 | Сообщение # 1
Thanks
В Keyvalues можно хранить нужную вам информацию, которую можно использовать не только во время работы сервера, но и после его перезапуска/падения/отключения. В EventScripts это KeyGroup.

Если вы создали группу и занесли в неё какие-то данные, то они будут храниться в памяти сервера аж до его отключения или пока вы сами не уничтожите эту группу. Чтобы данные сохранились и после отключения сервера, их нужно занести в файл, обычный текстовый документ, а потом просто загрузить из него эти данные в нужный вам момент и снова использовать.

Обычно Keyvalues представляет собой такую структуру:



В группе может быть сколько угодно ключей, в качестве которых в основном используют что-то уникальное, например, SteamId или IP игрока, или какой-то пароль. У каждого ключа могут быть параметры с разными значениями, например, убийств : 5, имя : enot

Пример создания и сохранения группы:

Код
public OnPluginStart()
{
    new Handle:kv = CreateKeyValues("section_name");
    KvJumpToKey(kv, "my_key", true);
    KvSetString(kv, "my_key_value", "Value");
    KvRewind(kv);

    KvJumpToKey(kv, "STEAM_0:0:12345", true);
    KvSetString(kv, "nick", "wS");
    KvSetString(kv, "game", "Counter Strike Source");
    KvRewind(kv);

    KeyValuesToFile(kv, "x.txt");
    CloseHandle(kv);
}

После запуска этого плагина, у вас появится новый файл cstrike/x.txt

Код
"section_name"
{
    "my_key"
    {
       "my_key_value" "Value"
    }
    "STEAM_0:0:12345"
    {
       "nick"   "wS"
       "game"   "Counter Strike Source"
    }
}

Вот так можно получить данные, которые мы записали ('nick' и 'game' ключа 'STEAM_0:0:12345'):

Код
public OnPluginStart()
{
    new Handle:kv = CreateKeyValues("section_name");
    if (!FileToKeyValues(kv, "x.txt")) {
        PrintToServer("Не удалось загрузить cstrike/x.txt");
    }
    else if (KvJumpToKey(kv, "STEAM_0:0:12345", false))
    {
        decl String:text[64];
        KvGetString(kv, "nick", text, sizeof(text));
        PrintToServer("nick = %s", text);
        KvGetString(kv, "game", text, sizeof(text));
        PrintToServer("game = %s", text);
    }
    else {
        PrintToServer("Не удалось найти ключ: STEAM_0:0:12345");
    }
    CloseHandle(kv);
}

Описание некоторых функций для работы с KeyValues.

Handle:CreateKeyValues(const String:name[], const String:firstkey[]="", const String:firstValue[]="");

Код
name - имя группы
firstkey - если указано, то будет создан ключ
firstValue - если указано, то созданному ключу установится значение

CreateKeyValues("group") выглядит так:

"group"
{
}

CreateKeyValues("group", "key", "value") выглядит так:

"group"
{
    "key" "value"
}

Создает новую структуру (группу) и возвращает её Handle, которое необходимо для получения/удаления/добавления данных в эту группу. Чтобы уничтожить/удалить группу и все данные в ней, просто закройте её Handle с помощью функции CloseHandle() - это нужно сделать обязательно, но только тогда, когда эта группа уже вам не нужна. Примечание: Если скрипт был отключен, он сам закроет все Handle, но если во время работы скрипта вы понасоздаете групп и не закроете их Handle, то это утечка, т.е. это плохо.

bool:FileToKeyValues(Handle:kv, const String:file[]); - загружает данные из файла
bool:KeyValuesToFile(Handle:kv, const String:file[]); - записывает данные в файл (сохранение группы)

Цитата
kv - это Handle созданной структуры
file - файл в cstrike/ (если ваш файл в папке cfg, то пишите cfg/ваш_файл.txt

Обе функции возвращают true в случае успеха, или false, если произошла ошибка


bool:KvJumpToKey(Handle:kv, const String:key[], bool:create=false);

Код
kv - Handle группы
key - ключ, который ищем
create - если укажете true, то ключ будет создан, если его нет


Устанавливает позицию в структуре группы так, чтобы вы могли работать с параметрами этого ключа, если он был найден или был создан. После того, как вы занесли/извлекли/удалили данные этого ключа, то нужно восстановить позицию - просто сделайте KvRewind(Handle:kv); и не ломайте голову над этим (kv - Handle группы).

Функции для работы с ключом и его параметрами:

// Устанавливаем значения
KvSetString(Handle:kv, const String:key[], const String:value[]);
KvSetNum(Handle:kv, const String:key[], value);
KvSetFloat(Handle:kv, const String:key[], Float:value);
KvSetVector(Handle:kv, const String:key[], const Float:vec[3]);
KvSetColor(Handle:kv, const String:key[], r, g, b, a=0);

// Получаем
KvGetString(Handle:kv, const String:key[], String:value[], maxlength, const String:defvalue[]="");
KvGetNum(Handle:kv, const String:key[], defvalue=0); - возвращает целое число
Float:KvGetFloat(Handle:kv, const String:key[], Float:defvalue=0.0); - с точкой
KvGetVector(Handle:kv, const String:key[], Float:vec[3], const Float:defvalue[3]);
KvGetColor(Handle:kv, const String:key[], &r, &g, &b, &a);

bool:KvGetSectionName(Handle:kv, String:section[], maxlength);
Так можно получить имя ключа/группы, что зависит от текущей позиции в структуре.

KvDeleteThis(Handle:kv); - удалить ключ
bool:KvGotoFirstSubKey(Handle:kv) - установить позицию на первом попавшемся ключе

bool:KvGotoNextKey(Handle:kv, bool:keyOnly=true);
Устанавливает позицию к следующему ключу (сверху вниз). Вернет false, если ключей уже нет.
Если keyOnly true, то будут учитываться только ключи, иначе и параметры.

Если вы хотите хранить в такой базе статистику игроков (много данных), то лучше используйте MYSQL. Просто когда в базе будет немало данных, то работать с такой группой будет мучение для сервера.
 
_wS_ Дата: Пятница, 13.01.2012, 10:45:35 | Сообщение # 2
Thanks
Запустить цикл по всем ключам в группе можно так:

Код
public OnPluginStart()
{
    new Handle:kv = CreateKeyValues("");
    if (FileToKeyValues(kv, "x.txt") && KvGotoFirstSubKey(kv, true)) {
        decl String:KeyName[40];
        do {
            if (KvGetSectionName(kv, KeyName, sizeof(KeyName))) {
                PrintToServer("Найден ключ: %s", KeyName);
            }
        }
        while (KvGotoNextKey(kv, true));
    }
    else {
        PrintToServer("cstrike/x.txt отсутствует или пуст");
    }
    CloseHandle(kv);
}

Если вы часто используете группу, то сохраните её в глобальной Handle: переменной.
Не стоит злоупотреблять командой FileToKeyValues.
 
Scarface_slv Дата: Суббота, 17.03.2012, 13:18:29 | Сообщение # 3
Сообщений: 737
Репутация: 61 [ +/- ]
а можно еще пример удаления?
 
_wS_ Дата: Суббота, 17.03.2012, 14:26:08 | Сообщение # 4
Thanks
cfg/stats.txt :

Код
"stats"
{
     "STEAM_1"
     {
         "k" "1"
     }
     "STEAM_2"
     {
         "k" "2"
     }
     "STEAM_3"
     {
         "k" "3"
     }
}

Удаляем STEAM_2

Код
public OnPluginStart()
{
     new Handle:kv = CreateKeyValues("");
     if (FileToKeyValues(kv, "cfg/stats.txt") && KvJumpToKey(kv, "STEAM_2", false))
     {
         KvDeleteThis(kv);
         KvRewind(kv);
         KeyValuesToFile(kv, "cfg/stats.txt");
     }
     CloseHandle(kv);
}
 
Scarface_slv Дата: Суббота, 17.03.2012, 18:42:56 | Сообщение # 5
Сообщений: 737
Репутация: 61 [ +/- ]
Спасибо большое klas
 
IceMeN Дата: Воскресенье, 22.04.2012, 09:57:31 | Сообщение # 6
Сообщений: 47
Репутация: 5 [ +/- ]
Можно ли обновить группу, не перезапуская сервер?
Если можно, то какой функцией обновить данные в группе?


Сообщение отредактировал IceMeN - Понедельник, 23.04.2012, 06:56:40
 
_wS_ Дата: Понедельник, 23.04.2012, 23:17:50 | Сообщение # 7
Thanks
Что значит обновить? Я не понял что ты хочешь сделать. Если удалить все данные, то сделай CloseHandle(group_kv); и заного создай структуру (CreateKeyValues).
 
IceMeN Дата: Вторник, 24.04.2012, 00:16:11 | Сообщение # 8
Сообщений: 47
Репутация: 5 [ +/- ]
Ну то есть, допустим я создаю меню, которое добавит в группу например SteamID и ник игрока.
А у меня идет проверка игроков по SteamID из этого файла, из этой группы.

Так вот я через меню добавлю нового игрока. Мне нужно будет перезагружать сервер? Или плагин берет данные из файла прямо во время игры, а не хранит их в буфере...

Какой то бред получился, но может быть ты поймешь.
 
_wS_ Дата: Вторник, 24.04.2012, 00:33:05 | Сообщение # 9
Thanks
Перезагружать не надо, данные заносятся сразу, но если ты хочешь чтобы они сохранились в файле, надо сделать KeyValuesToFile - это делают для того, чтобы после перезапуска сервера данные не потерялись, а их можно было загрузить из файла и использовать снова. И старайся использовать KeyValuesToFile так, чтобы это было не сильно часто (во избежание лагов, если вдруг). Т.е если ты часто заносишь/удаляешь данные и хочешь их сохранить, то сохраняй в конце/начале раунда, или после старта/конца карты, если редко, то можно прям сразу сохранить (например, добавление/удаление админа и тд, в таком стиле).

Если тебе не нужны эти данные после перезапуска сервера, то нет смысла их записывать в файл, они будут храниться в Handle: переменной (глобальную сделай) и уничтожатся после откл сервера или если сделаешь CloseHandle. Я наверно лишнего наговорил, но надеюсь ответил на вопрос, ибо я его и правда не до конца понял.
 
IceMeN Дата: Вторник, 24.04.2012, 08:48:24 | Сообщение # 10
Сообщений: 47
Репутация: 5 [ +/- ]
Большое тебе спасибо!
Ответ на мой вопрос я получил. Так как ты расписал все очень хорошо и понятно.
 
Naykon Дата: Пятница, 11.05.2012, 16:10:55 | Сообщение # 11
Сообщений: 439
Репутация: -4 [ +/- ]
Code
public FreePlayerSelect(Handle:menu, MenuAction:action, client, option)
{
       if (action == MenuAction_Select)
       {   
    GetMenuItem(menu, option, FreeID, sizeof(FreeID), _, FreeName, sizeof(FreeName));
    UserFree = GetClientOfUserId(StringToInt(FreeID));
    if (UserFree > 1)
    {  
     new Handle:h = CreateKeyValues("FreeClient");  
     KvJumpToKey(h, FreeID, true);
     KvSetString(h, "name", FreeName);  
     KvRewind(h);  
     KeyValuesToFile(h, "cfg/FreeClient.txt");    

     PrintToChatAll("%N свободен", FreeName);  
     SetEntityRenderColor(UserFree, 204, 51, 204, 10);  
     playersFreeDay += 1;  
    }
    else PrintToChatAll("Ошибка или UserFree больше 2");
    }
}


Плагин не добавляет а заменяет игроков назначеные через меню. Т.е если я сначала выбрал Paul то он появился в txt, и если я потом выбираю Wania, то Paul заменяется на Wania(( как добавлять а не заменять7
 
_wS_ Дата: Пятница, 11.05.2012, 17:09:45 | Сообщение # 12
Thanks
В этой теме есть ответ. Ты каждый раз снова создаешь пустую группу, добавляешь игрока и сохраняешь, конечно же оно будет перезаписываться. Надо хранить Handle группы в глобальной переменной и не делать CloseHandle, если она тебе еще нужна.
 
ЙОДА Дата: Суббота, 26.05.2012, 01:20:16 | Сообщение # 13
Сообщений: 41
Репутация: 0 [ +/- ]
Было бы интересно узнать, возможно ли превратить Keyvalues в некий аналог MySQL, а именно - сделать так, чтобы в любой момент можно было открыть файл и изменить параметр любого ключа, не повредив остальное содержимое файла. Если возможно, то простенький пример, как изменить один параметр не повредив файл.


Сообщение отредактировал ЙОДА - Суббота, 26.05.2012, 01:22:45
 
_wS_ Дата: Суббота, 26.05.2012, 08:46:43 | Сообщение # 14
Thanks
Уже есть такой пример..

Код
new Handle:kv = CreateKeyValues("");
if (FileToKeyValues(kv, "x.txt") && KvJumpToKey(kv, "key"))
{
     KvSetString(kv, "key_value", "Value");
     KvRewind(kv);
     KeyValuesToFile(kv, "x.txt");
}
CloseHandle(kv);

Но если много записей в группе, то не стоит использовать KeyValues.
 
ЙОДА Дата: Суббота, 26.05.2012, 13:15:17 | Сообщение # 15
Сообщений: 41
Репутация: 0 [ +/- ]
Хм, все отлично, разобрался сам. Действительно, нужно было делать хэндл глобальным.


Сообщение отредактировал ЙОДА - Суббота, 26.05.2012, 18:17:16
 
Форум » SourceMod >> CS:Source >> CSGO » Уроки SourceMod (SourcePawn) Скриптинга » Keyvalues - База (группа) для хранения информации
  • Страница 1 из 3
  • 1
  • 2
  • 3
  • »
Поиск: