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

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

  • Страница 1 из 1
  • 1
Форум » SourceMod >> CS:Source >> CSGO » Уроки SourceMod (SourcePawn) Скриптинга » Оптимизация кода (советы, помощь) (Как сделать лучше)
Оптимизация кода (советы, помощь)
_wS_ Дата: Четверг, 31.05.2012, 02:11:07 | Сообщение # 1
Thanks
Задачу можно решить многими способами, но нужно уметь:

Код
- Укорачивать и оптимизировать код
- Не использовать лишнее (например, зачем создавать переменную, если она может не понадобиться)
- Не использовать часто одинаковый код (создавайте функции)
- Не злоупотреблять такими циклами, как OnGameFrame, OnPlayerRunCmd (даже избегать их)
- Не создавать "утечку памяти" (закрывать все ненужные Handle и т.д.)
- Понимать порядок выполнения команд и событий
- Делать нужные проверки (например, перед выдачей оружия игроку: он точно на сервере? жив? и т.д.)
- Не делать ненужные/лишние/повторные проверки в условиях
- Указывать массивам правильный размер (не создавать много лишних ячеек)
- И др.. (скажите, если я что-то упустил)

Если вы не уверены в коде или сомневаетесь, как что-то лучше сделать, можете писать в этой теме.

Некоторые Советы:

Код
// Так делать глупо:
if (GetClientTeam(client) == 2) ...
else if (GetClientTeam(client) == 3) ...

// Зачем повторно получать команду игрока, если мы уже сделали это?
// Сохраните её в переменной и уже с ней работайте:
new team = GetClientTeam(client);
if (team == 2) ...
else if (team == 3) ...

// Или можно сделать так. Это немного лучше, но особой разницы нет, делайте как вам удобнее.
switch (GetClientTeam(client))
{
    case 2:
    {
        // Ваш код, если это команда 2.
    }
    case 3:
    {
        // Ваш код, если это команда 3.
    }
    default:
    {
        // Ваш код, если это какая-то другая команда.
    }
}

// Если вам нужно сделать только одно сравнение, то создавать переменную нет смысла:
if (GetClientTeam(client) == 2) ...

На счет массивов:

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

На счет строк:

Код
// Готовим переменную для хранения строки.
// Старайтесь указывать такой размер, чтобы он делился на 4 без остатка.
// Например, если укажете 5, то он автоматом станет 8 байт, увеличится в большую сторону так, чтобы делилось на 4.
decl String:name[64];

// Вот так можно обезопасить строку.
// Это полезно, если хотим работать с переменной, но не уверены содержит ли она значение.
name[0] = 0; // 0 или '\0' это символ конца строки (все последующие символы обычно игнорируется)

// Команда для примера:
GetEntPropString(index, Prop_Data, "m_iName", name, sizeof(name));

// И ниже уже можно работать с этой переменной, не беспокоясь
if (!name[0]) .. // строка пустая

На счет if и else if:

Код
new x = 5;

// так плохо:

if (x == 2)
{
     // код
}
if (x == 5)
{
     // код
}

// так хорошо:

if (x == 2)
{
     // код
}
else if (x == 5)
{
     // код
}
else if (x == 7)
{
     // код
}
else
{
     // код
}

Если вы используете цикл for, while и тд, то:

- если ипользуете переменные внутри цикла, то объявляйте их перед циклом, а не внутри
- обрывайте цикл с помощью команд break, return, если он уже не нужен
 
Sunday Дата: Суббота, 14.07.2012, 03:05:09 | Сообщение # 2
Сообщений: 186
Репутация: 24 [ +/- ]
спасибо! Ваши знания на вес золота!
 
scorpion2904 Дата: Суббота, 24.11.2012, 13:41:55 | Сообщение # 3
Сообщений: 68
Репутация: 5 [ +/- ]
Что делает цикл OnGameFrame?
 
_wS_ Дата: Суббота, 24.11.2012, 18:56:24 | Сообщение # 4
Thanks
Code
public OnGameFrame()
{
     static x = 0;
     PrintToServer("%d", ++x);
}

Событие вызывается 66 раз в сек или 33/100 - зависит от tickrate.
 
TEIN Дата: Суббота, 13.04.2013, 15:33:19 | Сообщение # 5
Сообщений: 563
Репутация: 78 [ +/- ]
Тот же пример с командой игрока можно сделать так
Код
switch (GetClientTeam(client))
{
     case 1:
     {
         // Код для наблюдателей
     }
     case 2:
     {
         // Код для Террористов
     }
     case 3:
     {
         // Код для Спецназовцев
     }
}


Сообщение отредактировал DoK_1997 - Суббота, 13.04.2013, 15:35:14
 
Naykon Дата: Четверг, 08.05.2014, 13:19:11 | Сообщение # 6
Сообщений: 439
Репутация: -4 [ +/- ]
wS подскажи как избавиться от этого глупого предупреждения на этапе компиляции.. "warning 217: loose indentation" можно ли застявить компилятор не обращать внимания на эту ошибку (эта ошибка отвечает за табуляцию...) просто мешает рассмотреть реальные ошибки...
 
king(rus) Дата: Суббота, 14.06.2014, 06:52:29 | Сообщение # 7
Сообщений: 109
Репутация: 2 [ +/- ]
Цитата Naykon ()
wS подскажи как избавиться от этого глупого предупреждения на этапе компиляции.. "warning 217: loose indentation" можно ли застявить компилятор не обращать внимания на эту ошибку (эта ошибка отвечает за табуляцию...) просто мешает рассмотреть реальные ошибки...


Можно, прописав:
Код
#pragma tabsize 0
 
Valeriks Дата: Пятница, 20.06.2014, 15:14:53 | Сообщение # 8
Сообщений: 100
Репутация: 3 [ +/- ]
_wS_ поясни пожалуйста одну вещь
вот такой расклад
Код
if (x == 2)
{
        // код
}
else if (x == 5)
{
        // код
}
else if (x == 7)
{
        // код
}
else
{
        // код
}

выполняется поочередно?
т.е. если в первом if (x == 2) ничего не сходится то дальше выполняется else if (x == 5) так?
И если во всех параметрах ничего не сошлось то просто выполняется else {} Правильно?


Сообщение отредактировал Valeriks - Пятница, 20.06.2014, 15:16:04
 
_wS_ Дата: Пятница, 20.06.2014, 15:41:21 | Сообщение # 9
Thanks
Да, по порядку.
 
serm Дата: Среда, 10.09.2014, 14:29:15 | Сообщение # 10
Сообщений: 137
Репутация: 7 [ +/- ]
Появились вопросы .
Если я объявляю переменную так #define stroka "lol" - и использую 1 раз, стоит ли ее убирать ? (Использую для быстрого редактирования квара ...)
Если плагин из 1000 ... более строк (но функции выполняющиеся внутри короткие) имеет смысл его укорачивать (Типа чем меньше размер файла тем меньше нагрузки он дает)?
Как лучше объявлять переменную внутри плагина new или decl или ( static - вдруг он меньше нагрузки даст pipec )?
Если я создам Например OnGameFrame, OnPlayerRunCmd и тут же сделаю return
Код

public OnGameFrame() return;

Будет ли от этого нагрузка ?

Добавлено (10.09.2014, 14:24:57)
---------------------------------------------
Почему если сделать так то вылезет warning

Код

TeleportEntity(id, NULL_VECTOR, NULL_VECTOR, {0.0, 0.0, 0.0});

а так нет
Код

new Float:f_Pos[3];
TeleportEntity(id, NULL_VECTOR, NULL_VECTOR, f_Pos);

Добавлено (10.09.2014, 14:29:15)
---------------------------------------------
Почему при вот таких функциях выходит warning

Код

public MyFunc(id, Float:f_Pos[3]){
TeleportEntity(id, NULL_VECTOR, NULL_VECTOR, f_Pos); // warning 213
AnyFunction(f_Pos); // warning 213
}

public AnyFunc(Float:f_Pos[3]){
// code ...
}
 
BarD Дата: Среда, 10.09.2014, 16:08:22 | Сообщение # 11
Сообщений: 943
Репутация: 137 [ +/- ]
Цитата serm ()
TeleportEntity(id, NULL_VECTOR, NULL_VECTOR, {0.0, 0.0, 0.0});

Возможно, массив последний у тебя не Float. Надо так: TeleportEntity(id, NULL_VECTOR, NULL_VECTOR, Float:{0.0, 0.0, 0.0});
 
serm Дата: Среда, 10.09.2014, 16:28:16 | Сообщение # 12
Сообщений: 137
Репутация: 7 [ +/- ]
Цитата BarD ()
Возможно, массив последний у тебя не Float. Надо так: TeleportEntity(id, NULL_VECTOR, NULL_VECTOR, Float:{0.0, 0.0, 0.0});

Это уже исправил, а вот остальное пока что нет . Есть идеи ?
 
_wS_ Дата: Суббота, 29.09.2018, 19:35:06 | Сообщение # 13
Thanks
В прошлом ответе serm'у я был не совсем прав, поэтому удалил его и даю новый, т.к. опыта чуть больше стало (некоторые мне в этом помогли, например Kailo).

Цитата serm ()
Если я объявляю переменную так #define stroka "lol" - и использую 1 раз, стоит ли ее убирать ?

Я раньше думал что это как глобальная переменная, но #define, sizeof(), enum - всё это просто подставляется во время компиляции и после неё пропадает, и на память никак не влияет, поэтому их можно использовать сколько угодно. Ещё можно не бояться делать #include, т.к. если какой-то натив, событие, enum и тд не используются в вашем коде, то компилятор просто всё это вырежет (отдекомпильте плагин и посмотрите что в нём осталось).

Цитата BarD ()
Код
public OnGameFrame() return;

Будет ли от этого нагрузка ?

Скорее всего да, т.к. компилятор оставляет (не вырезает) это public событие в коде, а значит оно будет вызываться.

На счет new и decl :

SourceMod wiki говорит, что нужно быть осторожным при чтении переменной, которая была объявлена с помощью decl, т.к. если мы не присвоили значение такой переменной и пытаемся его вывести, то может и сервер упасть. Например, в случае с строками, можно обезопасить переменную так:

Код
decl String:s[4];
s[0] = 0; // Говорим что первый символ это конец строки (пустая строка). Последующие символы игнорируются (но в них мусор, неизвестные данные).
PrintToServer("s = '%s'", s); // Норм работает: s = ''

Ещё советуют никогда вообще не использовать decl, кроме некоторых случаев с массивами.
new String:s[4]; // Pawn устанавливает каждому индексу значение 0.
decl String:s[4]; // Объявление переменной без какого-либо значения (в ней сейчас мусор).

Насколько мне известно, оба эти варианта равны:

Код
new g_x = 5;

1.

public OnGameFrame()
{
    new x = g_x;
    if (x) ...
}

2.

public OnGameFrame()
{
    decl x;
    if ((x = g_x)) ..
}

Если вы используете массивы в OnGameFrame, то лучше использовать static, decl, или создать глобальную переменную.
Если массив немаленький, то decl наверно делать не стоит, т.к. часто будет выделяться/освобождаться память.
Насколько мне известно, static ничем не отличается от глобальной переменной, кроме области видимости.
 
Форум » SourceMod >> CS:Source >> CSGO » Уроки SourceMod (SourcePawn) Скриптинга » Оптимизация кода (советы, помощь) (Как сделать лучше)
  • Страница 1 из 1
  • 1
Поиск: