←  Pytania

AMXX.pl: Support AMX Mod X i SourceMod

»

Kolejne skrócenie pętli (for) graczy?

  • +
  • -
Ossal - zdjęcie Ossal 21.02.2015

Gracze w cs są indexowani od 1 do 32, jak jest powiedzmy 5 graczy na serwie  i wyjdzie ten z indexem 3 to gracze 4 i 5 zostają "zdegradowani" do indexu o jeden mniejszego (po czym następuje magiczne przerzucenie wszystkich danych w każdym pluginie na nowe indexy, sam na wiem jak to się dzieję :D) Czy w związku z tym wolno nam założyć że natrafienie na niepołączonego gracza w pętli (!is_user_connected(id)) to koniec możliwości na trafienie na połączonego?
"Kolejne" w temacie odnosi się do tego, że zamiast robić for(new i=1;i<33;i++) robi się for(i=1;i<MaxPlayers;i++) gdzie MaxPlayers to zmienna globalna z przypisanym get_maxplayers() w plugin_init <== choć nie wiem po co to piszę, bo chyba każdy to wie :D
Mój pomysł to coś takiego:
for(i=1;i<=MaxPlayers;i++){
             if(!is_user_connected(i)) break
             //nasz warunek lub nic
             //kod wykonany na graczu
}
A pytanie do was jest proste: czy jest pewność że w 100% sytuacji taka pętla zadziała poprawnie?
No i oczywiście czy jest sens coś takiego robić, nawet przy pętlach wykonywanych co chwila zaoszczędzenie będzie niewielkie, ale biorąc pod uwagę serwer 32 sloty i grający obecnie np 6 osób, to wydawać by się mogło, że coś tam  jednak oszczędzimy.
Z góry dzięki za odpowiedź :)
Użytkownik radim edytował ten post 21.02.2015 21:03
Odpowiedz

  • +
  • -
Rivit - zdjęcie Rivit 21.02.2015


Gracze w cs są indexowani od 1 do 32, jak jest powiedzmy 5 graczy na serwie i wyjdzie ten z indexem 3 to gracze 4 i 5 zostają "zdegradowani" do indexu o jeden mniejszego (po czym następuje magiczne przerzucenie wszystkich danych w każdym pluginie na nowe indexy, sam na wiem jak to się dzieję :D)

 

 

Wydaje mi się że indexy nie "podsuwają się".

for(i=1;i<MaxPlayers;i++)

Na:

for(i=1;i<=MaxPlayers;i++)

Widzę, że Ty też wszędzie doszukujesz się oszczędności, mój człowiek :*

Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 21.02.2015

Nie ma żadnego "magicznego" przesuwania indeksów, dopóki gracz nie opuści serwera lub mapa się nie zmieni, ma stały indeks. Więc nie, nie możesz przerwać pętli gdy trafisz na pierwszego niepołączonego gracza.
GwynBleidD (21.02.2015 20:03):
Jeśli chcesz by pętla się wykonała dokładnie tyle razy, ile masz graczy na serwerze, użyj get_players.
Odpowiedz

  • +
  • -
Ossal - zdjęcie Ossal 21.02.2015

co do <= to oczywiście niedopatrzenie, takich błędów raczej nie robię :D
Jesteś pewien że indexy są stałe, a nowi gracze wskakują na miejsce rozłączonych?
Jak to, magia nie istnieje? :(

 


Użytkownik Ossal edytował ten post 21.02.2015 20:45
Odpowiedz

  • +
  • -
Rivit - zdjęcie Rivit 21.02.2015

Tak, tak jest.

Odpowiedz

  • +
  • -
Ossal - zdjęcie Ossal 22.02.2015

Dobra tamto było lekkomyślne troszkę. Zmieniamy taktykę:
 

#include <amxmodx>

new MaxPlayers=0
public plugin_init(){
	register_plugin("Nazwa Pluginu", "1.0", "Ossal")
}
public client_connect(id){
	if(id>MaxPlayers)
		MaxPlayers=id
}
public client_putinserver(id){
	if(id!=MaxPlayers) return
	do{
		MaxPlayers--
	}
	while(!is_user_connected(MaxPlayers))
}

Wówczas pętla będzie wyglądać tak samo jak standardowa [for(new i=1;i<=MaxPlayers;i++)], ale zmienna przechowująca get_maxplayers() będzie przechowywać inną liczbę (przy małej ilości graczy względem ilości slotów nawet sporo mniejszą)
Co powiecie na coś takiego? Nie sknociłem czegoś? Może mi ktoś powiedzieć czy coś takiego zaoszczędzi trochę zasobów? Przy jednej pętli graczy na rundę może nie specjalnie będzie widać różnicę, ale z perspektywy całej mapy lub przy wykonywaniu pętli np przy każdej śmierci może już bardziej? Dzięki za odpowiedzi :)
PS jeżeli gracze dostają index przed putinserver to proszę o poprawkę :)


Użytkownik Ossal edytował ten post 22.02.2015 13:10
Odpowiedz

  • +
  • -
Ossal - zdjęcie Ossal 22.02.2015

Boshe, co ja napisałem :o Oczywiście że gracz dostaje index wcześniej, dostaje go w pierwszej funkcji wywołanej gdy wchodzi na serwer czyli prawdopodobnie client_connecting(), sprawdzę potem, która jest pierwsza na pewno :P client_putinsever jest ostatnią funkcją tego typu :P
//Proszę o dorzucenie powyższego do posta powyżej, a ten post do usunięcia :)

Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 22.02.2015

Szukasz optymalizacji nie tam gdzie trzeba... Nawet jeśli pętla wykonuje się przy każdej śmierci gracza, załóżmy że śmierć wywołuje się średnio raz na 5 sekund, a pętla po graczach wykona się w ile? 0.0001 sekundy? Rozumiem, czasem w pętli jest faktycznie dużo do zrobienia, ale taka pętla:

    for (new id=1; id<=maxplayers; ++id) {
        if (!client_connected(id))
            continue;

        // jakiś dłużej wykonujący się kod
    }
to próba skrócenia tej pętli w jakikolwiek sposób skróci czas jej wykonywania o 0.5% może troszkę więcej, bo przecież i tak kod wewnątrz pętli się dla nieistniejących graczy nie wykona, a sprawdzenie czy gracz jest połączony i pominięcie danej iteracji pętli gdy nie jest zajmuje ułamek sekundy...

Jeśli z jakiegoś powodu chcesz, by pętla wykonała się dokładnie tyle razy, ile masz graczy użyj:

new Players[32], Num, i;
get_players(Players, Num);

for(i=0; i < Num; i++)
{
    new id=Players[i];

    // jakiś dalszy kod
}
ale ma to sens gdy z jakiegoś naprawdę konkretnego powodu chcesz by pętla nie wykonała się ani razu więcej, np licznik i z pętli wykorzystujesz gdzieś dalej do określenia ile razy pętla się wykonała (np gdy szukasz tą pętlą gracza konkretnego i na nim zatrzymujesz pętlę a następnie chcesz określić z jakiegoś powodu który z kolei był to gracz).

dużo ważniejsze jest optymalizowanie wywołań długiego kodu w eventach takich jak prethink, add to fullpack, niwelowanie wykonujących się co chwilę tasków, niwelowanie kodu który wstrzymuje serwer na dłuższą chwilę (bo np zawiera pętlę która wykonuje się 10000 razy). Warto użyć do tego typu optymalizacji profilera: https://forums.allie...00&postcount=87ale pamiętaj, że nie nadaje się on na działające serwery, jedynie do szukania problemów i rzeczy do zoptymalizowania.
Odpowiedz