как понять static decl Handle..

Тема в разделе "Программирование / Скриптинг", создана пользователем NagarD, 27 янв 2014.

  1. NagarD

    NagarD

    Сообщения:
    412
    Симпатии:
    170
    Объясните пожалуйста.
    1. Первое что меня интересует - как мне понимать Handle и decl.

    PHP:
    new Handle:EnabledMode INVALID_HANDLE;
    decl String:userid[15];
    2. Что за модификаторы (может и не модификаторы) static и stock
    О статик понял что это типа протект переменная её не будет видно вне функции и она инициализируеться только один раз.

    PHP:
    static iPrevButtons[MAXPLAYERS+1];

    stock Function()
    {
         
    //
    }
    3. Волшебные константы MAXPLAYERS и MaxClients

    PHP:
    for (new 1<= MaxClientsi++)
    {
        if (
    IsPlayerAlive(i)){
            
    //
        
    }
    }
    new 
    iPrevButtons[MAXPLAYERS+1];
    Интересно как MaxClients делает i индексом игрока?

    4. Что такое &?

    PHP:
    public Action:OnPlayerRunCmd(client, &buttons, &impulseFloat:vel[3], Float:angles[3], &weapon
    {
        if (
    buttons IN_USE)
        {
            
    //
        
    }
    }
    Наверное все знают пример с коробкой и дыркой в ней. Коробка - область в памяти, дырка - ссылка на эту область. Хотелось бы увидеть что-то подобное
     
  2. R1KO

    R1KO Супер-модератор

    Сообщения:
    6.005
    Симпатии:
    2.994
    NagarD, 3. Индекс игрока может быть от 1 до 64 (вроде бы), а MaxClients это по сути и есть число 64, и ты цикло перебираешь все числа от 1 до 64 с условием IsClientInGame, и если число проходит эту проверку то оно есть индексом игрока.
    if (IsPlayerAlive(i)) - так нельзя делать. Не известно в игре ли игрок. Будет куча ошибок в логе. Сначала надо IsClientInGame.
    MAXPLAYERS - Это тоже вроде число 64 но к нему прибавляем 1 т.к. первый индекс массива будет 0.

    decl - создаешь переменную не присваивая ей значения или что-то в этом роде
     
    NagarD нравится это.
  3. NagarD

    NagarD

    Сообщения:
    412
    Симпатии:
    170
    R1KO, выходит на сервере может быть максимум 64 игрока? Оффтоп
     
  4. R1KO

    R1KO Супер-модератор

    Сообщения:
    6.005
    Симпатии:
    2.994
    NagarD, да
    Насколько я понял он работает быстрее new и создает переменную с хламом внутри
     
    Последнее редактирование: 27 янв 2014
    NagarD нравится это.
  5. KorDen

    KorDen Atra esterní ono thelduin!

    Сообщения:
    2.194
    Симпатии:
    1.398
    1. Handle - типизатор переменной (фактически как и String) - указывает что в переменной хранится ссылка наданныеь (на переменную, на таймер, на данные Trie/Array/KeyValues)
    Decl - начну с new. new при объявлении переменной гарантированно выставляет ей значение 0. Однако если брать тот же массив или строку, то нет смысла их полностью инициализировать, если в них сразу будут записываться данные. decl объявляет переменную, но изначально в ней будет мусор. Однако быстрее.
    decl не работает для глобальных переменных.
    Для строк (String) можно адже делать самодельную инициализацию нулем гораздо быстрее (если вдруг может случиться что значение не будет прописано)
    decl String:test[255];
    test[0]=0;
    Это быстрее, и для строк аналогично new String:test[255]; по результату. Фактически да, дальше будет мусор, но строки обрабатываются до ноль-символа, и поэтому это аналогично.

    2. stock - часто используется в библиотеках типа morecolors или SMLib. Если stock-функция не вызывается нигде, то при компиляции она не будет вкомпилена в плагин.
    static - оптимизация. Например в функции OnPlayerRunCmd постоянно создается локальная переменная - это лишние затраты. А так фактически получится как глобальная переменная, т.е. она создастся один раз. Но при этом глобально к ней обратиться нельзя.

    3. индекс игрока, (а так же индекс энтити тела живого игрока, который равен индексу игрока) - как уже сказал рико - от 1 до 64. 0 - консоль, больше 64 уже идут индексы энтитей мира (те же бочки и любые другие объекты т.д.) Фактически да, в Source максимум 64 игрока (исключение - Garry's Mod (128), но под него нет SM), иногда 65 когда STV.
    MAXPLAYERS - константа, вшивается при компиляции (64)
    MaxClients - это не константа, это серверная глобальная переменная (не переменная всмысле sv_ и т.д., а именно внутренняя в SM), равна количеству слотов на сервере. Т.е. если сервер запущен на 32 человека, то цикл будет пробегать от 1 до 32, а не до 64.

    4. & - передача по адресу (по сути аналогична Си, но не нужно явно разадресовывать такие переменные).
    Т.е. если обычно ты передаешь в функцию копию переменной, и изменения идут только локально, то здесь ты передаешь оригинальную переменную, и если ее изменять, то будет изменяться оригинал Пример:
    PHP:
    func1()
    {
        new 
    a=5;
        
    PrintToServer("%d\n",a); // 5
        
    func2(a);
        
    PrintToServer("%d",a); //10
    }
    func2(&num)
    {
        
    num=num+5// или можно num=10; и т.д.
    }
     
    White Wolf, R1KO и NagarD нравится это.
  6. NagarD

    NagarD

    Сообщения:
    412
    Симпатии:
    170
    C decl думаю абсолютно разобрался. По сути decl просто размечает память, но не форматирует её, а new форматирует.
    stock выходить в плагинах вообще не нужно, только во всяких расширениях.
    Если правильно знаю, то MAXPLAYERS не глобальная константа, а дефайн глобальный, так выходит?
    MaxClients - ну это просто. Могу добавить, что она еще динамическая.
    Немного понял о передачи по ссылке.
    А вот Handle вообще в голову не влазит.
     
  7. FrozDark

    FrozDark Команда сайта HLMod Модератор

    Сообщения:
    1.761
    Симпатии:
    1.916
    проще говоря, Handle указатель на ячейку с памятью, например, переменных

    Оффтоп - Handle содержит переменную, которая выделяется через С++. Просто SourcePawn не может управлять памятью напрямую и содержит только статическое.
     
    NagarD нравится это.
  8. NagarD

    NagarD

    Сообщения:
    412
    Симпатии:
    170
    FrozDark, хорошо, а зачем Handle нужен? Если объявить Handle не приравняв к INVALID_HANDLE, что будет? Оффтоп
     
  9. Reiko1231

    Reiko1231 AlexTheRegent

    Сообщения:
    238
    Симпатии:
    569
    В четвертом неправильно ответили, для твоего вопроса это не передача по адресу, а побитовое И.
    Здесь в переменной buttons находятся все нажатые клавиши (их значения, если быть точнее. ибо можно забиндить "использовать" на Z, и тогда IN_USE будет означать, что нажата Z, а не E), и через & проверяется, содержится ли там IN_USE флаг. Вообщем википедия, статья про битовые операции, а то я чувствую, что объяснил не очень.
     
    KorDen, R1KO, NagarD и ещё 1-му нравится это.
  10. R1KO

    R1KO Супер-модератор

    Сообщения:
    6.005
    Симпатии:
    2.994
    Ничего не будет.
    Так же как и
    PHP:
    new i;
    При создании присвоит i значение 0
    Точно так же и
    PHP:
    new Handle:hCvar;
    При создании присвоит hCvar значение INVALID_HANDLE
     
  11. KorDen

    KorDen Atra esterní ono thelduin!

    Сообщения:
    2.194
    Симпатии:
    1.398
    Да
    Не в расширениях, а в подключаемых библиотеках (файлах .inc)
    Тут ты немного смешал в кучу. Поясню. Есть фраза "Пианино делает музыку". Тогда твоя фраза была бы "MAXPLAYERS выходит не музыка, а пианино глобальное?" - #define - это объявление константы. и MAXPLAYERS это константа, но да, фактически она объявляется #define в одном из стандартных включаемых файлов.
    Точно так же ты же не называешь переменную "Это нью" (от объявления new)
    Она устанавливается при запуске сервера и фактически равна значению +maxplayers в строке запуска (либо прибавляется один если STV включен)
    Да, тут Reiko правильно объяснил, я не о том & говорил, я о тех, которые в заголовке функции.
    Ну ты же сам объяснил точь-в-точь :)
     
    R1KO и NagarD нравится это.
  12. KorDen

    KorDen Atra esterní ono thelduin!

    Сообщения:
    2.194
    Симпатии:
    1.398
    Про побитовые операции (buttons & IN_USE), попробую объяснить попроще и нагляднее.
    Мне кажется лучше привести примером админские флаги, проще будет понять.
    Смотри, предположим у админа флаги "abce"
    В двоичном представлении, которое вернет GetUserFlagBits(client), это выглядит как 10111.
    Код:
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 - битовое представление
    t s r q p o z n m l k j i h g f e d c b a - флаги
    Далее мы применяем маскирование.
    Маска - это собственно то что идет после &. если в маске 0, то в результате будет всегда 0, если в маске 1 - то будет то что в переменной (т.е. если был 0 - останется 0, если была 1 - останется 1)
    Например мы берем GetUserFlagBits(client) & ADMFLAG_ROOT
    Код:
    t s r q p o z n m l k j i h g f e d c b a
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 - флаги админа
    0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - маска, проще говоря двоичное представление константы ADMFLAG_ROOT
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 = 0 = false - результат
    А если берем GetUserFlagBits(client) & ADMFLAG_GENERIC
    Код:
    t s r q p o z n m l k j i h g f e d c b a
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 - флаги админа
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 - маска, проще говоря двоичное представление константы ADMFLAG_GENERIC
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 = 10 = true - результат
    Помни, что false = 0, а все остальное - true. Т.е. в данном случае где будет GENERIC вернется true, т.к. у админа есть этот флаг и он выделяется по маске
     
    NagarD и R1KO нравится это.
  13. R1KO

    R1KO Супер-модератор

    Сообщения:
    6.005
    Симпатии:
    2.994
    Не буду создавать новую тему.
    Тоже кое что спрошу. Код из Weapon Restrict:
    PHP:
    if(!g_bSpamProtectPrint[client])
        {
            if(
    Restrict_IsSpecialRound() && !Restrict_AllowedForSpecialRound(id))
            {
                
    PrintToChat(client"\x01\x0B\x04[SM] %T %T"weaponNames[_:id], client"SpecialNotAllowed"client);
            }
            else if(
    team == CS_TEAM_CT)
            {
                
    PrintToChat(client"\x01\x0B\x04[SM] %T %T"weaponNames[_:id], client"IsRestrictedPickupCT"clientRestrict_GetRestrictValue(teamid));
            }
            else
            {
                
    PrintToChat(client"\x01\x0B\x04[SM] %T %T"weaponNames[_:id], client"IsRestrictedPickupT"clientRestrict_GetRestrictValue(teamid));
            }
            
    g_bSpamProtectPrint[client] = true;
            
    CreateTimer(PRINTDELAYResetPrintDelayclient);
        }
    Мне не понятна роль _:id
     
  14. KorDen

    KorDen Atra esterní ono thelduin!

    Сообщения:
    2.194
    Симпатии:
    1.398
    R1KO, хе, странно, обычно это не нужно.. Хотя.. скинь строчку объявление этого самого id...
     
  15. R1KO

    R1KO Супер-модератор

    Сообщения:
    6.005
    Симпатии:
    2.994
    KorDen, вот еще
    PHP:
    new defaultValuesCT[_:WeaponID];
    new 
    defaultValuesT[_:WeaponID];
    new 
    perPlayer[_:WeaponID][MAXPLAYERS+1];
    new 
    bool:g_bOverideT[_:WeaponID];
    new 
    bool:g_bOverideCT[_:WeaponID];
    //Convar Handles
    new Handle:hRestrictCVarsT[_:WeaponID-4];//No shield, No None, No Defuser, No SCAR17
    new Handle:hRestrictCVarsCT[_:WeaponID-4];//No shield, No None, No C4, No SCAR17
    new Handle:g_version INVALID_HANDLE;
    new 
    CvarArrayHandleValCT[_:WeaponID];
    new 
    CvarArrayHandleValT[_:WeaponID];


    //
    for(new 0_:WeaponIDi++)
        {
            if(
    WeaponID:== WEAPON_NONE || WeaponID:== WEAPON_SHIELD || WeaponID:== WEAPON_SCAR17 || AllowedGame[WeaponID:i] == -|| (g_iGame == GAME_CSS && (AllowedGame[WeaponID:i] != && AllowedGame[WeaponID:i] != 2)) || (g_iGame == GAME_CSGO && (AllowedGame[WeaponID:i] != && AllowedGame[WeaponID:i] != 3)))
            {
                
    CvarArrayHandleValCT[WeaponID:i] = -1;
                
    CvarArrayHandleValT[WeaponID:i] = -1;
                continue;
            }
            if(
    WeaponID:!= WEAPON_DEFUSER)
            {
                if(
    WeaponID:!= WEAPON_C4)
                {
                    
    Format(cvarsizeof(cvar), "sm_restrict_%s_t"weaponNames[WeaponID:i]);
                }
                else
                {
                    
    Format(cvarsizeof(cvar), "sm_restrict_%s"weaponNames[WeaponID:i]);
                }
                
    Format(descsizeof(desc), "-1 = unrestricted, 0 = restricted, positive numbers = number allowed for Terrorists . Weapon:%s"weaponNames[WeaponID:i]);
                
    hRestrictCVarsT[x] = CreateConVar(cvar"-1"desc);
                
    CvarArrayHandleValT[WeaponID:i] = x;
                
    x++;
            }
            else
            {
                
    CvarArrayHandleValT[WeaponID:i] = -1;
            }
            if(
    WeaponID:!= WEAPON_C4)
            {
                if(
    WeaponID:!= WEAPON_DEFUSER)
                {
                    
    Format(cvarsizeof(cvar), "sm_restrict_%s_ct"weaponNames[WeaponID:i]);
                }
                else
                {
                    
    Format(cvarsizeof(cvar), "sm_restrict_%s"weaponNames[WeaponID:i]);
                }
                
    Format(descsizeof(desc), "-1 = unrestricted, 0 = restricted, positive numbers = number allowed for Counter-Terrorists. Weapon:%s"weaponNames[WeaponID:i]);
                
    hRestrictCVarsCT[y] = CreateConVar(cvar"-1"desc);
                
    CvarArrayHandleValCT[WeaponID:i] = y;
                
    y++;
            }
            else
            {
                
    CvarArrayHandleValCT[WeaponID:i] = -1;
            }
        }

    //

     
  16. KorDen

    KorDen Atra esterní ono thelduin!

    Сообщения:
    2.194
    Симпатии:
    1.398
    R1KO, а, WeaponID это по идее enum... но тогда не понятно зачем делать _: если i и так обычная переменная... Короче надо смотреть все в комплексе. Но в общем - это разные типы, _ обозначает отсутствие специального типа
     
    R1KO и NagarD нравится это.
  17. NagarD

    NagarD

    Сообщения:
    412
    Симпатии:
    170
    R1KO, Тоже самое, что и String:var
    Добавлено через 43 минуты
    И так, продолжим. Есть модификаторы переменных srting, handle, decl, float, даже enum, как сказано выше, и другие - области в памяти. Ключевым srting словом мы задаем тип переменной (а кому задаем?). Если тип строка, то это говорит (а кому не знаем), что те биты в памяти формируют символы, буквы, числа. Если Handle, то, не знаем кто, знает, что в той области памяти находится адрес какой-то сущности, а не число, или строка, так?. Вопрос, а для чего это нужно?
     
    Последнее редактирование: 28 янв 2014
  18. KorDen

    KorDen Atra esterní ono thelduin!

    Сообщения:
    2.194
    Симпатии:
    1.398
    Ну прям "Тот-Кого-Нельзя-Называть" :-D
    Вообще это указатели на предназначение переменной. Указываем мы это компилятору. Однако String это все же больше тип.
    Поясню - стандартно при объявлении через new выделяется 4 байта (int). А при указании String на каждую ячейку выделяется 1 байт.
    Точно так же ты можешь в качестве строки использовать new a[4096] вместо new String:a[4096], однако тогда будет выделено 4*4096=16 килобайт, вместо 4х, и получается что 12 килобайт будут попусту висеть.

    float задает метод хранения данных - тут стоит почитать про методы сохранения целых чисел и чисел с плавающей точкой в памяти компьютера. Тут компилятор будет ругаться что tag Mismatch для удобства программиста, потому что иначе в переменных будет каша, если присваивать int=float и наоборот.

    handle указывает что это адрес в памяти, а не число. Никаких специфичных изменений в принципе сохранения нет относительно стандартного, однако помогает не путаться.
     
    NagarD нравится это.
  19. Jak ozdoba na torcie

    Jak ozdoba na torcie Как украшение на торт

    Сообщения:
    26
    Симпатии:
    13
    Дополнение: Handle это 4bitжое число и другой плагин не может использовать его (Если его не клонировать).
     
    NagarD нравится это.
  20. FrozDark

    FrozDark Команда сайта HLMod Модератор

    Сообщения:
    1.761
    Симпатии:
    1.916
    каждому из String, Handle, bool можно перевести в простой integer

    Т.е. если я сделаю new Handle:hCvar = Handle:11354;
    можно вывести Handle как integer.
    В итоге PrintToChatAll("%d", _:hCvar) выведет в чат 11354 и не будет никаких ошибок при компиляции

    Я называю это _: опускание префикса

    Так же можно из bool сделать Handle или String просто выставив нужный префикс
     
    NagarD нравится это.