Доступ к готовым решениям

Переход в группу "Пользователь"

300.00 ₽
Одноразовый платёж
Быстрый переход в группу "Пользователи", без надобности написания постов и ожидания.

Покупка дает возможность:
Быть полноправным участником форума
Нормальное копирование кода
Создавать темы
Скачивать файлы
Доступ к архиву Pawno-Info

Урок Быстрый перебор игроков в сети.

Статус
В этой теме нельзя размещать новые ответы.

Tracker1

Специалист
Начну с предисловия.
Каждый раз, когда я захожу на форум, особенно в разделы вопросов или уроков, я натыкаюсь на подобные циклы
PHP:
for(new i=0;i<MAX_PLAYERS;i++)
или такие
PHP:
for(new i=0;i<GetMaxPlayers();i++)
В такие моменты у меня рождается чувство, что такты процессора проюбываются зря впустую.
И поэтому я решил показать быстрый способ перебора игроков в сети, без лишних итерации цикла.

Как же он работает?
Создаем один массив размером MAX_PLAYERS и переменную для контроля(предположим players[MAX_PLAYERS] и control).
При запуске мода заполняем массив -1 и обнуляем control. Когда у нас подключается игрок, мы записываем его ид в массив, увеличивая control.
При отключении игрока, мы просто ставим ид последнего на положение ида отключившегося игрока.
В переборе мы просто вместо playerid используем players и i<control.


Ну а теперь реализация кода.
к глобальным переменным добавляем
PHP:
new Players[500];
new players;
в public OnPlayerConnect
PHP:
Players[players++]=playerid;
в public OnPlayerDisconnect
PHP:
	for(new i=0;i<players;i++)
	{
		if(Players[i]==playerid)
		{
			Players[i]=Players[--players];
			Players[players]=-1;
                        break;
		}
	}
Вот и весь код.
Пример перебора игроков. Предположим у нас какой-нибудь ГФ-подобный мод, и нам надо отправить всем админам сообщение
PHP:
	for(new i=0;i<players;i++)
	{
		if(PlayerInfo[Players[i]][pAdmin]>0) SendClientMessage(Players[i],-1,"Прием");
	}
С JIT плагином, данная разработка быстрее чем Foreach
Код:
[22:51:24] Vectoral test
[22:51:24] 125 players connected
[22:51:24] 50-74 IDs Disconnected
[22:51:24] Starting main cycle 1_000_000 times
[22:51:41] Vectoral test DONE. Time: 16456 ms.
[22:51:41] 

[22:51:41] Tracker1's foreach test
[22:51:41] 125 players connected
[22:51:41] 50-74 IDs Disconnected
[22:51:41] Starting main cycle 1_000_000 times
[22:51:41] Tracker1's foreach test DONE. Time: 531 ms.
[22:51:41] 

[22:51:41] Y_Less's foreach test
[22:51:41] 125 players connected
[22:51:41] 50-74 IDs Disconnected
[22:51:41] Starting main cycle 1_000_000 times
[22:51:42] Y_Less's foreach test DONE. Time: 674 ms.
PHP:
new time = 0;
	//
	printf("Vectoral test");
	new PLAYERSVECTORAL;
	PLAYERSVECTORAL = cvector();
	for(new i=0;i<125;i++)
		cvector_push_back(PLAYERSVECTORAL,i);
	printf("125 players connected");
	for(new i=50;i<75;i++)
	{
		new idx = cvector_find(PLAYERSVECTORAL,i); // Find player
		if(idx !=-1){ // If idx == -1, vector isn't containing this player
			cvector_remove(PLAYERSVECTORAL,idx);
		}
	}
	printf("50-74 IDs Disconnected");
	printf("Starting main cycle "#PROFILING_ITERS" times");
	time=GetTickCount();
	for(new i=0;i<PROFILING_ITERS;i++)
	{
		for(new j=0,k=cvector_size(PLAYERSVECTORAL), playerid=0; j<k; j++)
		{
			playerid = cvector_get(PLAYERSVECTORAL, j); // get playerid
			if(playerid != -1)
			{
				continue;
			}
		}
	}
	printf("Vectoral test DONE. Time: %d ms.",GetTickCount()-time);
	//
	print("\n");
	//
	printf("Tracker1's foreach test");
	for(new i=0;i<125;i++)
		Players[players++]=i;
	printf("125 players connected");
	for(new i=50;i<75;i++)
	{
		for(new j=0;j<players;j++)
		{
			if(Players[j]==i)
			{
				Players[j]=Players[--players];
				Players[players]=-1;
				break;
			}
		}
	}
	printf("50-74 IDs Disconnected");
	printf("Starting main cycle "#PROFILING_ITERS" times");
	time=GetTickCount();
	for(new i=0;i<PROFILING_ITERS;i++)
		tforeach(x)
		{
			continue;
			#pragma unused x
		}
	printf("Tracker1's foreach test DONE. Time: %d ms.",GetTickCount()-time);
	//
	print("\n");
	//
	printf("Y_Less's foreach test");
	for(new i=0; i<125; i++)
		Itter_Add(Player, i);
	printf("125 players connected");
	for(new i=50;i<75;i++)
		Itter_Remove(Player, i);
	printf("50-74 IDs Disconnected");
	printf("Starting main cycle "#PROFILING_ITERS" times");
	time=GetTickCount();
	for(new i=0;i<PROFILING_ITERS;i++)
		foreach(new x:Player)
			continue;
	printf("Y_Less's foreach test DONE. Time: %d ms.",GetTickCount()-time);
	//
	print("\n");
	return 1;

Всё.

Update
Один быдлокодер любезно написал дефайн, чтобы было больше похоже на foreach от Y_Less.
PHP:
 ^_^ Nicholas_West: #define tforeach(%0) for(new _i, %0=Players[_i]; _i <players; %0=Players[++_i])
С ним перебор выглядит вот так
PHP:
tforeach(x)
{
if(PlayerInfo[x][pAdmin]>0) SendClientMessage(x,-1,"Прием");
}
 
Последнее редактирование:
Статус
В этой теме нельзя размещать новые ответы.
Сверху Снизу