[Include] foreach от ****** или как оно работает -
DANGER1979 - 14.05.2011
Я не сторонник чужих скриптов.
Но так сложилось что как только я какой то [Include] пытаюсь применить для своего серва, то случаются какие то непредвиденные ситуации.
Первым печальным моим опытом было использование mxINI. Там из-за того что параметры с одинаковым началом воспринимались как одинаковые. В итоге слетело куча аккаунтов и мы перешли на базу данных. Спасибо автору, иначе я бы не решился с ini переходить на MySQL.
Кстати плагин mysql единственное из сторонних разработок, что стоит у меня на сервере и работает корректно.
Дальше мы пытались перевести всё цыклы на foreach. Особенно было актуально это для стрим тачек, т.е. создание динамического массива стрим тачек для каждого игрока. В общем сервер при каждом рестарте вис так, что пинг показывало в клиенте, но сама игра зависала. При этом ни одна ркон команда в удалённой консоли не пахала. Приходилось просто ФС крашить сервер.
Потом я поставил плагин от инкогнито и отключил все свои скриптовые стримеры. В итоге по началу было вроде нормально. Но потом когда я пикапы и ЗД тексты перевёл тоже на этот стример, то всё начало жутко лагать, подгрузки были очень заметны. Я вывел счётчики на экран в диалоге и увидел ужас. Так каждому игроку грузилось по несколько тысяч объектов. В итоге я подумал, что где то в стримере идёт не корректное удаление объектов из динамических массивов.
Теперь я решил снова разобрать динамические массивы от ******.
Маленький Мануал по созданию динамических массивов,
может кому пригодиться и это чудо у него будет корректно работать
Для этого создаём
pawn Код:
#define MAX_STREAMEDCARS 100 // Максимальное количество тачек, которое может находится рядом возле игрока.
//допустим что на сервере не создастся ситуации при которой кол-во стрим-тачек выйдет за 100
new StreamedVehicle[MAX_PLAYERS][MAX_STREAMEDCARS];//массив хранения ИД тачек по каждому игроку
new StreamVehCount[MAX_PLAYERS];//глобальный счётчик
Потом в public OnGameModeInit() инициализируем массив
pawn Код:
public OnGameModeInit()
{
...
Itter_InitInternal(StreamedVehicle, MAX_PLAYERS, MAX_STREAMEDCARS);
return 1;
}
pawn Код:
stock Itter_InitInternal(arr[][], s0, s1)
{
for(new i = 0; i != s0; ++i)
{
for(new j = 0; j != s1; ++j)
{
arr[i][j] = -1;
}
}
}
Потом создаём заполнение массива в public OnVehicleStreamIn(vehicleid, forplayerid)
pawn Код:
public OnVehicleStreamIn(vehicleid, forplayerid)
{
...
new start;
Itter_AddInternal(start, StreamVehCount[forplayerid], StreamedVehicle[forplayerid], vehicleid);
return 1;
}
pawn Код:
stock Itter_AddInternal(&start, &count, array[], value)
{
if(array[value] != -1)
{
return 0;
}
count++;
if(start == -1)
{
start = value;
}
else if(start > value)
{
array[value] = start;
start = value;
}
else
{
new cur = start, last;
do
{
last = cur;
cur = array[cur];
if(cur > value)
{
array[value] = cur;
array[last] = value;
printf("1. count: %d, array[value:%d]: %d, array[last:%d]: %d", count, value, array[value], last, array[last]);
return 1;
}
}
while(cur != -1);
array[last] = value;
printf("2. count: %d, array[value:%d]: %d, array[last:%d]: %d", count, value, array[value], last, array[last]);
}
return 1;
}
Потом удаление в public OnVehicleStreamOut(vehicleid, forplayerid)
pawn Код:
public OnVehicleStreamOut(vehicleid, forplayerid)
{
...
new start;
Itter_RemoveInternal(start, StreamVehCount[forplayerid], StreamedVehicle[forplayerid], vehicleid);
return 1;
}
pawn Код:
stock Itter_RemoveInternal(&start, &count, array[], value)
{
if(start == -1)
{
return 0;
}
if(start == value)
{
start = array[value];
}
else
{
new cur = start;
while(array[cur] != value)
{
cur = array[cur];
if(cur == -1)
{
return 0;
}
}
array[cur] = array[value];
printf("3. count: %d, array[cur:%d]: %d, array[value:%d]: %d", count, cur, array[cur], value, array[value]);
}
array[value] = -1;
--count;
printf("4. count: %d, array[cur:%d]: %d, array[value:%d]: %d", count, cur, array[cur], value, array[value]);
return 1;
}
и на всякий случай очистку массива в public OnPlayerDisconnect(playerid, reason)
pawn Код:
public OnPlayerDisconnect(playerid, reason)
{
...
new start;
Itter_ClearInternal(start, StreamVehCount[playerid], StreamedVehicle[playerid]);
return 1;
}
pawn Код:
stock Itter_ClearInternal(&start, &count, array[])
{
if (start != -1)
{
new cur = start, next = array[cur];
start = -1; count = 0;
while (next != -1)
{
array[cur] = -1;
cur = next;
next = array[cur];
}
}
}
В итоге тачки добавлялись в массив, но не совсем корректно удалялись. Через некоторое время из-за переполнения сервер зависал. Это видимо проблема всех скриптов при попытке создания динамических массивов.
Теперь вопрос: "Что я сделал не так?"
P.S. Я то докопаюсь до истины, просто интересно, кто-нибудь использует эти сторонние ресурсы на серверах сампа под Windows? Не ужели у всех сразу всё глатко работает?
Может кто ещё сталкивался с проблемами в чужих серьёзных сторонних разработках (отбросив всякую чушь что пишет разная школота)?
Re: [Include] foreach от ****** или как оно работает -
DANGER1979 - 14.05.2011
Также добавил if(IsPlayerNPC(forplayerid)) return 1;
т.к. для ботов не надо что либо добавлять или удалять.
В общем вот как работает эта хрень
Код:
[23:25:00] 2. start:0,count:1, array[last:0]: 258
[23:25:00] 2. start:0,count:2, array[last:258]: 301
[23:25:00] 2. start:0,count:3, array[last:301]: 383
[23:25:00] 2. start:0,count:4, array[last:383]: 412
[23:25:00] 2. start:0,count:5, array[last:412]: 566
[23:25:18] 1. start:0,count:6, array[value:22]: 258, array[last:0]: 22
[23:25:18] 3. start:0,count:6, array[cur:22]: 301, array[value:258]: 301
[23:25:18] 4. start:0,count:5, array[value:258]: -1
[23:25:18] 3. start:0,count:5, array[cur:22]: 383, array[value:301]: 383
[23:25:18] 4. start:0,count:4, array[value:301]: -1
[23:25:18] 3. start:0,count:4, array[cur:22]: 412, array[value:383]: 412
[23:25:18] 4. start:0,count:3, array[value:383]: -1
[23:25:18] 3. start:0,count:3, array[cur:22]: 566, array[value:412]: 566
[23:25:18] 4. start:0,count:2, array[value:412]: -1
[23:25:18] 3. start:0,count:2, array[cur:22]: -1, array[value:566]: -1
[23:25:18] 4. start:0,count:1, array[value:566]: -1
[23:25:26] 3. start:0,count:1, array[cur:0]: -1, array[value:22]: -1
[23:25:27] 4. start:0,count:0, array[value:22]: -1
Сдесь мы видим что в первой строке
[23:25:00] 2. start:0,count:1, array[last:0]: 258
в ячейку array[0] заносится значение 258
а потом в ячейку array[258] заносится значение 301
т.е.
массив формируется не последовательно.
В итоге если потом использовать этот массив от 0 до #define MAX_STREAMEDCARS 100
то мы не найдём наши все значение, придётся проверять не пустая ли ячейка и прогонять до MAX_VEHICLES
Вот в этом здесь собака и зарыта.
Т.е. теряется вся оптимизация.
Кто нибудь переделывал эту хрень, чтобы массив записывался последовательно или сортировался сразу?
Re: [Include] foreach от ****** или как оно работает -
Fro1sha - 15.05.2011
Какая разница как хранить данные, павн не динамический. Оптимизация не теряется есть спец дефине
pawn Код:
#define foreach(%1,%2) \
for (new %2 = YSI_gS%1; %2 != -1; %2 = YSI_gA%1[%2])
Re: [Include] foreach от ****** или как оно работает -
Jon_De - 15.05.2011
у меня ysi_timers встают иногда тупо =\
Re: [Include] foreach от ****** или как оно работает -
DANGER1979 - 15.05.2011
Fro1sha,
1. что значит павн не динамический?
2. Всё в руках скриптера, можно создать динамические массивы и сделать сортировку, только это не факт что будет оптимизация ради чего всё стоило затевать, т.к. время будет потрачено на наполнение и работу с массивом, а потом ещё и на организацию цыкла проверки по массиву, с целью нахождения всех значения для данного игрока.
3. напиши мне это
Код HTML:
#define foreach(%1,%2) \
for (new %2 = YSI_gS%1; %2 != -1; %2 = YSI_gA%1[%2])
или это
Код:
#define foreachex(%1,%2) \
for (%2 = YSI_gS%1; %2 != -1; %2 = YSI_gA%1[%2])
на нормальным языке (без никаких макросов и сокращенных записей)
т.е. с учётом предыдущего составленного массива организуй цыкл проверки
4. Возможно я что-то не дорубаю. Буду очень признателен если кто-то поможет разобраться.
Re: [Include] foreach от ****** или как оно работает -
Fro1sha - 15.05.2011
Quote:
Originally Posted by DANGER1979
Fro1sha,
1. что значит павн не динамический?
2. Всё в руках скриптера, можно создать динамические массивы и сделать сортировку, только это не факт что будет оптимизация ради чего всё стоило затевать, т.к. время будет потрачено на наполнение и работу с массивом, а потом ещё и на организацию цыкла проверки по массиву, с целью нахождения всех значения для данного игрока.
3. напиши мне это
Код HTML:
#define foreach(%1,%2) \
for (new %2 = YSI_gS%1; %2 != -1; %2 = YSI_gA%1[%2])
или это
Код:
#define foreachex(%1,%2) \
for (%2 = YSI_gS%1; %2 != -1; %2 = YSI_gA%1[%2])
на нормальным языке (без никаких макросов и сокращенных записей)
т.е. с учётом предыдущего составленного массива организуй цыкл проверки
4. Возможно я что-то не дорубаю. Буду очень признателен если кто-то поможет разобраться.
|
1. То что ты задаешь размер массива и не можешь больше его изменить.
3.
pawn Код:
stock AddBySorted(array[], value, size = sizeof array)
{
for ( new i; i != size; i++ )
{
if ( value >= array[i] )
{
for ( new k = size - 1; k != i; k-- )
{
array[k] = array[k - 1];
}
array[i] = value;
return 1;
}
if ( array[i] == -1 )
{
array[i] = value;
return 1;
}
}
return 0;
}
Эта функция добавляет в массив по порядку и отсортировано.
pawn Код:
for ( new i = 0; array[i] != -1; i++ )
Пробежаться по массиву.
Re: [Include] foreach от ****** или как оно работает -
DANGER1979 - 15.05.2011
Спасибо за функцию сортировку. Потом проверю. Ей можно заменить ф-ию Itter_AddInternal, но возможно придётся переписывать Itter_RemoveInternal.
Но это не совсем то, что я просил
напиши мне это
Код:
#define foreach(%1,%2) \
for (new %2 = YSI_gS%1; %2 != -1; %2 = YSI_gA%1[%2])
на нормальным языке (без никаких макросов и сокращенных записей)
т.е. с учётом предыдущего составленного массива организуй цыкл проверки.
Я просто не совсем понимаю как при этих всяких тупых YSI_gS%1 и YSI_gA%1 будет выглядеть цыкл.
Re: [Include] foreach от ****** или как оно работает -
Fro1sha - 15.05.2011
pawn Код:
for (new i = YSI_gSPlayer; i != -1; i = YSI_gAPlayer[i])
YSI_gS - индекс
YSI_gC - кол-во элементов
YSI_gA - сам массив де все лежит
Re: [Include] foreach от ****** или как оно работает -
DANGER1979 - 15.05.2011
А где в этом цыкле приращение?
т.е. как я понял цыкл стартует со значение YSI_gSPlayer (0)
до значение покуда не найдёт пустую ячейку (-1)
А где сам счётчик? (i++)
и как понять i = YSI_gSPlayer; и i = YSI_gAPlayer[i] в одном цыкле два присваивания одной и той же переменной?
Re: [Include] foreach от ****** или как оно работает -
Fro1sha - 15.05.2011
Допустим добавляем элементы в массив 1, 3, 2. Индекс равен 1.
Элемента в массиве располагаются так:
0 = -1
1 = 2
2 = 3
3 = -1
4 = -1
Цикл:
pawn Код:
new i = YSI_gSPlayer
new i = 1
i != -1
i = YSI_gAPlayer[1] // в следующем пробеге i = 2
i = YSI_gAPlayer[2] // в следующем пробеге i = 3
i = YSI_gAPlayer[3] // в следующем пробеге i = -1 закончить цикл
Куда еще проще объяснить я не знаю)