Keyvalues - База (группа) для хранения информации
| |
_wS_
|
Дата: Пятница, 13.01.2012, 10:36:41 | Сообщение # 1 |
|
В 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 |
|
Запустить цикл по всем ключам в группе можно так:
Код 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 |
|
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 [ +/- ]
|
|
Спасибо большое
|
|
| |
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 |
|
Что значит обновить? Я не понял что ты хочешь сделать. Если удалить все данные, то сделай CloseHandle(group_kv); и заного создай структуру (CreateKeyValues).
|
|
| |
IceMeN
|
Дата: Вторник, 24.04.2012, 00:16:11 | Сообщение # 8 |
|
Сообщений: 47
Репутация: 5 [ +/- ]
|
|
Ну то есть, допустим я создаю меню, которое добавит в группу например SteamID и ник игрока. А у меня идет проверка игроков по SteamID из этого файла, из этой группы.
Так вот я через меню добавлю нового игрока. Мне нужно будет перезагружать сервер? Или плагин берет данные из файла прямо во время игры, а не хранит их в буфере...
Какой то бред получился, но может быть ты поймешь.
|
|
| |
_wS_
|
Дата: Вторник, 24.04.2012, 00:33:05 | Сообщение # 9 |
|
Перезагружать не надо, данные заносятся сразу, но если ты хочешь чтобы они сохранились в файле, надо сделать 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 |
|
В этой теме есть ответ. Ты каждый раз снова создаешь пустую группу, добавляешь игрока и сохраняешь, конечно же оно будет перезаписываться. Надо хранить 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 |
|
Уже есть такой пример..
Код 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 |
|
| |
|