Просмотр полной версии : [Вопрос] Использование флагов в полном объеме
Elrmrnt-Kritik
18.01.2018, 00:21
Всем привет. Собственно, такой вопросик нарисовался у меня. Как известно, в некоторых командных процессорах есть возможность создавать флаги.
Ну, понятное дело, что общество, как и всегда, делится на тех, кто за и против их использования. Пусть каждый останется при своем мнении.
Однако, я лишь хочу научиться использовать их в полном объеме. А для того в первую очередь понять суть их. Судя по INC, макросом flags заменяется на создание отдельной функции с названием самой команды (упускаю факт существования префикса). А что дальше-то сервер делает с этой функцией и каким образом идет это установление маски?
И немного конкретного примера. Есть, например, система админ-уровней:
#define ADMIN_MIN 1
#define ADMIN_MED 2
#define ADMIN_MAX 3
flags:command_1(ADMIN_MIN);
flags:command_2(ADMIN_MED);
flags:command_3(ADMIN_MAX);
public OnPlayerCommandReceived(playerid, cmd[], params[], flags)
{
if((flags & ADMIN_MIN) > AdminLevel[playerid])
return SendClientMessage(playerid, -1, "your text min") & 0;
else if((flags & ADMIN_MED) > AdminLevel[playerid])
return SendClientMessage(playerid, -1, "your text med") & 0;
else if((flags & ADMIN_MAX) > AdminLevel[playerid])
return SendClientMessage(playerid, -1, "your text max") & 0;
return 1;
}
То есть для commad_1 нужен как минимум первый уровень, для command_2 нужен второй, а command_3 - как минимум третий. Правильно ли реализован данный код и как он сработает?
Пока писал, задумался, а как лучше же будет? :scratch_one-s_head:
#define ADMIN_MIN 1
#define ADMIN_MED 2
#define ADMIN_MAX 3
или
enum
{
ADMIN_NONE,
ADMIN_MIN,
ADMIN_MED,
ADMIN_MAX
};
pawnoholic
18.01.2018, 01:51
Согласно из Википедии:
В программировании понятие флаг относится к одному или нескольким битам памяти, используемым для хранения двоичной комбинации или кода, который характеризует состояние некоторого объекта. Флаги обычно входят в определённые структуры данных, такие как записи баз данных, и их значения, как правило, связаны со значением структур данных, частью которых они являются. Во многих случаях двоичное значение флага представляет собой кодированное представление одного из нескольких возможных состояний или статусов объекта. В других случаях двоичные значения флагов могут представлять собой один или несколько атрибутов в битовом поле, зачастую связанных с возможностями или доступом, например, «может быть записано в», или «может быть удалено». Однако флагам могут быть назначены и другие значения. Один из вариантов использования флагов состоит в маркировке для назначения структуры данных к последующей обработке.
Исходя из вашего вопроса, судя по синтаксису вы интересуетесь реализацией флагов в Pawn.CMD.
Ваш код должен иметь примерно такой вид:
#include <Pawn.CMD>
enum(<<=1)
{
ADMIN_LEVEL_1 = 1,
ADMIN_LEVEL_2,
ADMIN_LEVEL_3
};
flags:command_1(ADMIN_LEVEL_1);
cmd:command_1(playerid, params[])
{
// code here
return 1;
}
flags:command_2(ADMIN_LEVEL_2);
cmd:command_2(playerid, params[])
{
// code here
return 1;
}
flags:command_3(ADMIN_LEVEL_3);
cmd:command_3(playerid, params[])
{
// code here
return 1;
}
public OnPlayerCommandReceived(playerid, cmd[], params[], flags)
{
if ((flags & ADMIN_LEVEL_1) && AdminLevel[playerid] < 1)
return 0;
if ((flags & ADMIN_LEVEL_2) && AdminLevel[playerid] < 2)
return 0;
if ((flags & ADMIN_LEVEL_3) && AdminLevel[playerid] < 3)
return 0;
return 1;
}
public OnPlayerCommandPerformed(playerid, cmd[], params[], result, flags)
{
if(result == -1)
{
if (flags & ADMIN_LEVEL_1)
SendClientMessage(playerid, -1, "Your error text");
if (flags & ADMIN_LEVEL_2)
SendClientMessage(playerid, -1, "Your error text");
if (flags & ADMIN_LEVEL_3)
SendClientMessage(playerid, -1, "Your error text");
return 0;
}
return 1;
}
http://pro-pawn.ru/showthread.php?13892-Pawn-CMD-%D1%81%D0%B0%D0%BC%D1%8B%D0%B9-%D0%B1%D1%8B%D1%81%D1%82%D1%80%D1%8B%D0%B9-%D0%B8-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%BD%D1%8B%D0%B9-%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BE%D1%80&p=87758&viewfull=1#post87758
Elrmrnt-Kritik
18.01.2018, 17:38
А если рассмотреть, например, ситуацию, когда доступ к команде имеют игроки фракций 1 и 5, либо 1,2 и 4... Для каждой комбинации таких фракций придется создавать свой флаг и вручную проверять в паблике, вызываемом при отправке команды?
Типа такого:
public OnPlayerCommandReceived(playerid, cmd[], params[], flags)
{
if((flags & TEAM_GOS) && Player[playerid][pTeam] != 1 && Player[playerid][pTeam] != 4)
return SendClientMessage(playerid, -1, "your text min") & 0;
return 1;
}
И переменную TEAM_GOS для флага нужно будет лепить в единый enum со всеми флагами (как в примере выше, туда же, где и права администратора), либо же иначе?
pawnoholic
18.01.2018, 18:01
А если рассмотреть, например, ситуацию, когда доступ к команде имеют игроки фракций 1 и 5, либо 1,2 и 4... Для каждой комбинации таких фракций придется создавать свой флаг и вручную проверять в паблике, вызываемом при отправке команды?
Типа такого:
public OnPlayerCommandReceived(playerid, cmd[], params[], flags)
{
if((flags & TEAM_GOS) && Player[playerid][pTeam] != 1 && Player[playerid][pTeam] != 4)
return SendClientMessage(playerid, -1, "your text min") & 0;
return 1;
}
И переменную TEAM_GOS для флага нужно будет лепить в единый enum со всеми флагами (как в примере выше, туда же, где и права администратора), либо же иначе?
Все флаги должны быть перечислены в одном множестве, иначе их значения будут совпадать.
Elrmrnt-Kritik
27.01.2018, 00:36
Все флаги должны быть перечислены в одном множестве, иначе их значения будут совпадать.
Я же правильно понимаю, больше тридцати двух флагов нельзя?
Я же правильно понимаю, больше тридцати двух флагов нельзя?
Нельзя больше 32 в одном энуменаторе
Я же правильно понимаю, больше тридцати двух флагов нельзя?
Если что, никто не запрещал указывать начало отсчёта для перечисления
enum(<<=1)
{
ADMIN_LEVEL_1 = 1,
ADMIN_LEVEL_2,
ADMIN_LEVEL_3,
...,
ADMIN_LEVEL_32
};
enum(<<=1)
{
ADMIN_LEVEL_33 = ADMIN_LEVEL_32,
ADMIN_LEVEL_34,
ADMIN_LEVEL_35,
...,
ADMIN_LEVEL_64
};
Elrmrnt-Kritik
16.02.2018, 01:20
Уж больше недели наивно думал, что все же соображу. Но не судьба.В вашем коде ADMIN_LEVEL_32 и ADMIN_LEVEL_33 приравнены. А они не пересекутся?
$continue$
16.02.2018, 05:56
А, самому проверить? Через print/printf?
По идей пересечение должно быть, но я не уверен. Так, что совету не ждать, а проверить. Если все же пересечения есть, то +1 к началу отсчёта в 2 переселении.
Если что, никто не запрещал указывать начало отсчёта для перечисления
enum(<<=1)
{
ADMIN_LEVEL_1 = 1,
ADMIN_LEVEL_2,
ADMIN_LEVEL_3,
...,
ADMIN_LEVEL_32
};
enum(<<=1)
{
ADMIN_LEVEL_33 = ADMIN_LEVEL_32,
ADMIN_LEVEL_34,
ADMIN_LEVEL_35,
...,
ADMIN_LEVEL_64
};
Не прокатит, в ячейке может хранится лишь 32 бита, поэтому да, больше 32 хранить нельзя.
Elrmrnt-Kritik
24.03.2018, 02:24
Не знаю почему, но как-то забыл за эту тему. Спасибо доставил, у кого не было. Извините, что не сделал раньше)
Я хотел лишь уточнить некоторые моменты.
1. По большому счету компилятор представляет названия команд и значения из enum в двоичной системе счисления, а потом просто идет сверка? Тогда возникает и еще один вопрос: почему именно &? Ведь если биты одинаковые в двух числах, то и сами числа равны.
2. Флагами я могу (хотя мне простительно xD) называть только то, где присутствует этот алгоритм, либо вообще любую побитовую операцию?
3. Можно ли использовать флаги как-то еще, помимо флагов в командах на базе pawncmd? (я ранее лишь с битами работал в отдельности. Для систем обучения и лицензий)
Не знаю почему, но как-то забыл за эту тему. Спасибо доставил, у кого не было. Извините, что не сделал раньше)
Я хотел лишь уточнить некоторые моменты.
1. По большому счету компилятор представляет названия команд и значения из enum в двоичной системе счисления, а потом просто идет сверка? Тогда возникает и еще один вопрос: почему именно &? Ведь если биты одинаковые в двух числах, то и сами числа равны.
2. Флагами я могу (хотя мне простительно xD) называть только то, где присутствует этот алгоритм, либо вообще любую побитовую операцию?
3. Можно ли использовать флаги как-то еще, помимо флагов в командах на базе pawncmd? (я ранее лишь с битами работал в отдельности. Для систем обучения и лицензий)
1) В данном случае необходимо лишь сравнивать один бит, соответственно, что и делает операция AND. При сравнении вы сильно бы зависели от значения других битов, что нарушает логику флагов. Тем не менее, вы можете сравнивать несколько битов, используя операцию AND и OR.
if (flags & (BIT_FLAG_1 | BIT_FLAG_2)) {
// code..
}
2) Нет, поскольку в программирование есть определение bit flag. Оно говорит о том, что флаг - состояние бита (то есть 0 или 1) в числе. Соответственно, можно сказать, что флаги - упакованные boolean переменные.
3) Можно, если учитывать предыдущий ответ.
Elrmrnt-Kritik
15.06.2018, 01:25
Спасибо. Закройте пожалуйста тему.
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot