[Include] foreach от ****** или как оно работает
#1

Я не сторонник чужих скриптов.
Но так сложилось что как только я какой то [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? Не ужели у всех сразу всё глатко работает?
Может кто ещё сталкивался с проблемами в чужих серьёзных сторонних разработках (отбросив всякую чушь что пишет разная школота)?
Reply
#2

Также добавил 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
Вот в этом здесь собака и зарыта. Т.е. теряется вся оптимизация.

Кто нибудь переделывал эту хрень, чтобы массив записывался последовательно или сортировался сразу?
Reply
#3

Какая разница как хранить данные, павн не динамический. Оптимизация не теряется есть спец дефине
pawn Код:
#define foreach(%1,%2) \
    for (new %2 = YSI_gS%1; %2 != -1; %2 = YSI_gA%1[%2])
Reply
#4

у меня ysi_timers встают иногда тупо =\
Reply
#5

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. Возможно я что-то не дорубаю. Буду очень признателен если кто-то поможет разобраться.
Reply
#6

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++  )
Пробежаться по массиву.
Reply
#7

Спасибо за функцию сортировку. Потом проверю. Ей можно заменить ф-ию 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 будет выглядеть цыкл.
Reply
#8

pawn Код:
for (new i = YSI_gSPlayer; i != -1; i = YSI_gAPlayer[i])
YSI_gS - индекс
YSI_gC - кол-во элементов
YSI_gA - сам массив де все лежит
Reply
#9

А где в этом цыкле приращение?
т.е. как я понял цыкл стартует со значение YSI_gSPlayer (0)
до значение покуда не найдёт пустую ячейку (-1)

А где сам счётчик? (i++)

и как понять i = YSI_gSPlayer; и i = YSI_gAPlayer[i] в одном цыкле два присваивания одной и той же переменной?
Reply
#10

Допустим добавляем элементы в массив 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 закончить цикл
Куда еще проще объяснить я не знаю)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)