PDA

Просмотр полной версии : [Вопрос] Использование флагов в полном объеме



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;
}

DeimoS
18.01.2018, 06:34
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
Все флаги должны быть перечислены в одном множестве, иначе их значения будут совпадать.

Я же правильно понимаю, больше тридцати двух флагов нельзя?

Long-
27.01.2018, 12:38
Я же правильно понимаю, больше тридцати двух флагов нельзя?

Нельзя больше 32 в одном энуменаторе

DeimoS
07.02.2018, 16:52
Я же правильно понимаю, больше тридцати двух флагов нельзя?

Если что, никто не запрещал указывать начало отсчёта для перечисления

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 переселении.

ziggi
16.02.2018, 08:51
Если что, никто не запрещал указывать начало отсчёта для перечисления

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? (я ранее лишь с битами работал в отдельности. Для систем обучения и лицензий)

VVWVV
24.03.2018, 03:52
Не знаю почему, но как-то забыл за эту тему. Спасибо доставил, у кого не было. Извините, что не сделал раньше)

Я хотел лишь уточнить некоторые моменты.
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
Спасибо. Закройте пожалуйста тему.