Skocz do zawartości
Mario

[ROZWIĄZANY]Przegrany czas na serwerze.

Rekomendowane odpowiedzi

Cześć. Chcę zrobić naliczanie przegranego czasu na serwerze. Wiem, że można zrobić to na timerze i tam dodawać co 1 minutę 1 do zmiennej i już będzie czas w minutach, tylko że, nie jest to chyba za bardzo optymalne. Zacząłem robić coś w tym stylu, tak jak napisał Kaz w tym temacie: http://pawno.pl/index.php?/topic/20561-gettickcount-liczenie-czasu-gry-na-serwerze-i-inne/ i mój kod wygląda tak: 

 

stock GetTime(playerid)

	        return gettime()-PlayerInfo[playerid][pCzasGry];


PlayerInfo[playerid][pCzasGry] = gettime(); //to w OnPlayerConnect

 

 

No i teraz, tak jak w/w temacie Kaz napisał, można zrobić cmd na wyświetlanie przegranego czasu:

 

CMD:time(playerid, params[])
{
    new tstring[50];
    format(tstring, 50, "Grasz już: %d minut",GetTime(playerid)/60000);
    SendClientMessage(playerid, -1, tstring);
    return 1;
}

Tylko że, chciałbym też zrobić opcję zliczania całego przegranego czasu gry, czyli po każdym wyjściu z serwera, aby do zmiennej dodawało przegrany czas i tak w kółko. Wiem, że chyba musiał bym zrobić nową zmienną PlayerInfo[playerid][pCalyCzasGry] i do niej zliczać ten cały czas, ale jak to zrobić na podstawie w/w kodu? Jeszcze też nie wiem jak zrobić, aby np. w wiadomości pokazywało "Grasz już: %d godzin %d minut %d sekund" przykładowo, czyli jak przegramy 60 sekund to dodaje minutę, jak przegramy 60 minut to dodaje jedną godzinę itd. :)

 

Za pomoc like, wiem, że trochę się rozpisałem, ale chciałem jak najlepiej wytłumaczyć o co mi chodzi.

 

Edytowane przez Mario

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie jestem tak bardzo doświadczony, ale przychodzi mi na myśl rozwiązanie. Jeżeli Gracz wchodzi na serwer to wyciągasz czas wejścia do gry, a jeżeli wychodzi to również wyciągasz i potem wyliczasz różnicę, a potem tą różnicę dodajesz do enuma czasu gry. 

Edytowane przez Frank

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Póki nikt nie odpisuje to możesz pobawić się.

Wtedy kiedy gracz się zespawnuje to wrzucasz do stocka jego playerid i używasz funkcji na pobieranie czasu i zwracasz zmienną tekstową z której potem wyciągniesz konkretne liczby. (używając format do zapisania)  Zapisujesz sobie to gdzieś, może do SQL (przyda się w panelach) bądź innej globalnej zmiennej np. w stringu. Jeżeli będzie wychodzić to robisz całą algorytmikę czyli obliczasz różnicę między czasem wyjściowym i wejściowym. Jeżeli zapisałeś to w stringu to trzeba sscanfem wyciągnąć dane: sscanf(cos, "p<cos>ddd", cos) i robisz odejmowanie i zapisujesz już to wszystko do właściwego miejsca czasu gry. Tyle że trzeba pamiętać żeby nie nadpisać zmiennej, a ją dodać tak jakbyś zliczał sume: suma += time (czyt. suma = suma + time). 

Edytowane przez Frank

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Rób w timerze. Nie wiadomo ile pamięci pobiera, ale prawdopodobnie tak mało, że musiałbyś zrobić ich naprawdę setki, żeby były jakieś negatywne skutki. Tylko najlepiej stwórz globalny. Ten sposób dwa posty wyżej zje o wiele więcej niż jeden timer, bo korzysta z tablic i zapisu do SQL.

 

Chodziło mu o coś takiego:

1. sprawdzasz która jest godzina, gdy gracz wejdzie na serwer

2. zapisujesz mu to do zmiennej

3. gdy wychodzi sprawdzasz ile czasu minęło od godziny wejścia

4. resztę znasz

 

ale bez timera i tak nie będziesz mógł na bieżąco edytować statystyk.

Edytowane przez Skrypter

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

A jak zrobić, że jak mam czas w minutach naliczony do zmiennej, np. wartość zmiennej CzasOnline = 100 to jak zrobić, aby wyciągnąć godziny z tego, czyli było by w tym wypadku 1 godzina 40 minut.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Najlepsze rozwiązanie to czas unixowy. Po co robić tysiące timerów, które dodatkowo nie są idealne co do sekundy?

Wchodzi - pobierasz czas funkcją gettime() i zapisujesz do jakiejś tablicy. Jak gracz wychodzi, to pobierasz z danych gracza (np. z bazy danych) czas jaki już przegrał, dodajesz do niego gettime() - tablica[playerid] i zapisujesz tą sumę do bazy.

Jak chcesz sprawdzić komendą ile już w sumie gra, to ta sama czynność, co przy wychodzeniu, tyle że nie zapisujesz tego, a wyświetlasz.

Co do wyświetlania czasu w postaci godzin, minut i sekund - prosta matematyka. 1h to 60 minut, 1 minuta to 60 sekund.

stock ConvertSec(seconds, &days ,&hours, &minutes)
{
	days = seconds / 86400;
	seconds -= days * 86400;
	hours = seconds / 3600;
	seconds -= hours * 3600;
	minutes = seconds / 60;
}

Użycie:

new czas[3];
ConvertSec(TUTAJ TA SUMA, czas[0], czas[1], czas[2]); //czas[0] to dni, [1] godziny a [2] sekundy

Mam nadzieję że sobie poradzisz :)

Edytowane przez Michalec
Dziwnie układa kod w znaczniku [code], dodatkowo brakuje tego w pasku z bbcode, chyba że jestem ślepy.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
O 20.12.2015 at 20:09, Skrypter napisał:

Rób w timerze. Nie wiadomo ile pamięci pobiera, ale prawdopodobnie tak mało, że musiałbyś zrobić ich naprawdę setki, żeby były jakieś negatywne skutki. Tylko najlepiej stwórz globalny. Ten sposób dwa posty wyżej zje o wiele więcej niż jeden timer, bo korzysta z tablic i zapisu do SQL.

Ważne że dla każdego gracza wykonuje się po kilkaset jak nie kilkadziesiąt tysięcy razy. To na pewno nie jest optymalne.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

@Michalec Jest o tym na Wikipedii, jest o tym na niniejszym Forum, ale jeżeli ktoś do tej pory tego jeszcze nie ogarnął, bo chociażby szukał jak szukał, to widocznie to nie na jego głowę, bo dodawanie, odejmowanie, mnożenie i dzielenie jest w podstawówce.

15 godzin temu, Frank napisał:

Ważne że dla każdego gracza wykonuje się po kilkaset jak nie kilkadziesiąt tysięcy razy. To na pewno nie jest optymalne.

Jeżeli komuś to działa i jest z tego zadowolony to fajno :D

Zakładając nowy temat Autor mógł był sprawdzić czy na Forum nie ma już innego podobnego, ale po co... :)

Edytowane przez PrzMas
literówka

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

PrzMas, nie każdy jest nie wiadomo jakim programistą od razu. Po drugie, szukałem i to dużo, lecz sposoby, które były nie działały jak powinny. Co do tej optymalizacji to przecież pisałem na górze wątku coś o tym,  bo wiem jak zrobić zliczanie przegranego czasu za pomocą timera, ale nie będzie to optymalne, dlatego założyłem ten temat, aby dowiedzieć się jakie są inne sposoby na zrobienie tego zliczania.

Edytowane przez Mario

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

@Mario Toteż nie bez powodu się odezwałem, bo sam pisałem jakiś czas temu na tym forum o czymś, co może Ci się przydać, natomiast ze mnie ani magister informatyki ani matematyk ani programista - po prostu czasem trzeba sobie nad czymś samemu posiedzieć i pomyśleć.

Na wejście zapisujesz do zmiennej per-player (np. PVar) aktualny czas unixowy pobrany za pomocą funkcji gettime, natomiast cała rzecz dzieje się na wyjściu, kiedy to wyliczasz różnicę pomiędzy aktualnym czasem (znów funkcja gettime) a tym zapisanym na wejściu, którą to [różnicę] możesz sobie z kolei przekonwertować/przeliczyć na czas sformatowany w postaci godziny, minuty, sekundy w taki sposób, jak Ci to napisali wyżej. W Twoim przypadku nawet nie musi Cię interesować jak ten czas unixowy jest generowany, istotą jest, że to jest aktualny czas (na moment wywołania tejże funkcji w kodzie) wyrażony w sekundach i tylko taka wiedza jest Ci potrzebna na taki Twój użytek, jak w tym temacie to opisałeś.

Tak szczerze to jeżeli byłeś w stanie skonstruować te timer'y to powinieneś też poradzić sobie bez problemu z tą jedną funkcją gettime, tylko musisz popatrzeć i pomyśleć.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
O 22.12.2015 at 22:28, Frank napisał:

Ważne że dla każdego gracza wykonuje się po kilkaset jak nie kilkadziesiąt tysięcy razy. To na pewno nie jest optymalne.

Ale wiesz, że timery korzystają z procesora gracza a w stronę serwera idzie tylko informacja? Jeden globalny jest jak najbardziej ok. "Nieoptymalność" liczników to jeden z mitów SA-MPa. Jeśli spełniasz wymagania GTA to możesz śmiało je dodawać (oczywiście jeśli ich kod nie przeciąża serwera, to jest bardzo ważne).

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
11 godzin temu, Skrypter napisał:

Ale wiesz, że timery korzystają z procesora gracza a w stronę serwera idzie tylko informacja? Jeden globalny jest jak najbardziej ok. "Nieoptymalność" liczników to jeden z mitów SA-MPa. Jeśli spełniasz wymagania GTA to możesz śmiało je dodawać (oczywiście jeśli ich kod nie przeciąża serwera, to jest bardzo ważne).

Timery korzystają z procesora gracza? W jaki sposób niby :o 

Co do problemu:

Zmienne:

MySQL: czas_gry_total INT;  SAMP: czas_gry_total, czas_gry_current.

Przy wejściu czas_gry_current = gettime();
Przy wyjściu zapytanie "czas_gry_total = czas_gry_total + %d", czas_gry_current.

W ten sposób nie masz żadnych timerów pętli czy czego tam. Komenda na serwerze:

możesz skorzystać z ConvertTime wcześniej wspomnianego i robisz:
czas gry całkowity korzystając z danych pobranych z mysql + czas aktualnej sesji
czas aktualnej sesji na podstawie zmiennych

W razie niejasności lub jeśli potrzebujesz kodu a sam koncept nie starcza - pisz ;)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie wiem czemu wszyscy przejmują się tak optymalnością, myślicie że ktoś zwróci uwagę na te utracone milisekundy? Zresztą 3/4 tych serwerów i tak nie osiągnie więcej niż 50 graczy, gracze nie będą siedzieć ze stoperem w łapie i mierzyć utracone milisekundy ;-;

To tylko SA-MP, a wiele osób przeżywa jakby był to najważniejszy projekt w ich życiu

Nie wiem czy dobrze zrozumiałem, ale jeżeli chcesz zmierzyć czas gry gracza to GetTickCount załatwi sprawę.

Podczas wchodzenia gracza do gry zapisuj do zmiennej/PVara (ważne by było per-player) to co zwróci Sobie GetTickCount, a podczas wychodzenia oblicz różnicę tego co znowu zwróci Sobie funkcja GetTickCount, a tego co masz zapisane w zmiennej gracza i już masz czas gracza online w milisekundach. Podziel przez 60000, i już masz przybliżony czas w minutach

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
11 godzin temu, Skrypter napisał:

Ale wiesz, że timery korzystają z procesora gracza a w stronę serwera idzie tylko informacja? (...)

Bardzo ciekawa hipoteza...

12 godzin temu, Skrypter napisał:

(...) Jeden globalny jest jak najbardziej ok. "Nieoptymalność" liczników to jeden z mitów SA-MPa. Jeśli spełniasz wymagania GTA to możesz śmiało je dodawać (oczywiście jeśli ich kod nie przeciąża serwera, to jest bardzo ważne).

Użycie timer'a w tym przypadku albo w taki sposób jak to opisałeś to zwykła amatorszczyzna.

23 godzin temu, PrzMas napisał:

Zakładając nowy temat Autor mógł był sprawdzić czy na Forum nie ma już innego podobnego, ale po co... :)

§ II Tematy
2. Używaj opcji szukaj, aby sprawdzić czy odpowiedź na Twoje pytanie nie została już udzielona w innym wątku.
§ III Posty
5. Nie pomagaj na siłę, jeśli nie masz pojęcia o danym temacie nie wypowiadaj się i nie komentuj innych wypowiedzi.

@Skrypter, @bocian941, @¥: Ten temat nie jest warty tylu postów, ile już zostało w nim napisanych - nie będzie przełomu, nie zostało już nic więcej do wniesienia, Autor ma już wystarczająco szeroki wybór.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
6 godzin temu, bocian941 napisał:

Timery korzystają z procesora gracza? W jaki sposób niby :o 

Co do problemu:

Zmienne:

MySQL: czas_gry_total INT;  SAMP: czas_gry_total, czas_gry_current.

Przy wejściu czas_gry_current = gettime();
Przy wyjściu zapytanie "czas_gry_total = czas_gry_total + %d", czas_gry_current.

W ten sposób nie masz żadnych timerów pętli czy czego tam. Komenda na serwerze:

możesz skorzystać z ConvertTime wcześniej wspomnianego i robisz:
czas gry całkowity korzystając z danych pobranych z mysql + czas aktualnej sesji
czas aktualnej sesji na podstawie zmiennych

W razie niejasności lub jeśli potrzebujesz kodu a sam koncept nie starcza - pisz ;)

Bylo juz to napisane na samym poczatku. Tylko po co obciazac serwer

 

6 godzin temu, bocian941 napisał:

Timery korzystają z procesora gracza? W jaki sposób niby :o 

Co do problemu:

Zmienne:

MySQL: czas_gry_total INT;  SAMP: czas_gry_total, czas_gry_current.

Przy wejściu czas_gry_current = gettime();
Przy wyjściu zapytanie "czas_gry_total = czas_gry_total + %d", czas_gry_current.

W ten sposób nie masz żadnych timerów pętli czy czego tam. Komenda na serwerze:

możesz skorzystać z ConvertTime wcześniej wspomnianego i robisz:
czas gry całkowity korzystając z danych pobranych z mysql + czas aktualnej sesji
czas aktualnej sesji na podstawie zmiennych

W razie niejasności lub jeśli potrzebujesz kodu a sam koncept nie starcza - pisz ;)

Oczywiscie, ze korzystaja z procesora. Mozesz to latwo sprawdzic.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
22 godzin temu, Skrypter napisał:

Wyzej tzw. Janusz programowania.

Dziad swoje, baba swoje.

A co z dostępem np. do zmiennych zaalokowanych w pamięci procesu serwera, który to [dostęp] odbywa się z poziomu kodu owego timer'a?
Może cały kod gamemode'a jest uruchamiany i wykonywany na urządzeniu klienta?

22 godzin temu, Skrypter napisał:

Bylo juz to napisane na samym poczatku. Tylko po co obciazac serwer

(...)

Oczywiscie, ze korzystaja z procesora. Mozesz to latwo sprawdzic.

Oczywiście, że można, choćby z datą i godziną z wykorzystaniem timer'a, podczas gdy serwer jest uruchomiony na maszynie znajdującej się w innej strefie czasowej niż klient (gracz). Pobierana będzie wówczas data i godzina serwera (albo taka, jaka jest ustawiona na jego maszynie) a nie klienta. Funkcja gettime zwraca czas unixowy bez uwzględnienia strefy czasowej, natomiast jeśli chodzi o wartości tej funkcji zwracane przez jej trzy zmienne to w nich jest już uwzględniona ta strefa czasowa oraz czas letni/zimowy. Dodatkowo pojawia się tu kolejny argument w dyskusji. Gdy mówimy o funkcji zwracającej przez zmienną (przekazaną jako argument) to znaczy, że do funkcji jest przekazywany adres zmiennej, która ma zostać nadpisana w wyniku działania tej funkcji - niemożliwym jest dostęp z poziomu klienta do pamięci procesu serwera, ponieważ klient i serwer są fizycznie na osobnych maszynach.

P.S.
§ III Posty
2. Zabronione jest pisanie kilku wiadomości pod rząd w niedługim odstępie czasu, używaj opcji "modyfikuj".

Edytowane przez PrzMas
liczba poj./mn.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
22 godzin temu, Skrypter napisał:

Bylo juz to napisane na samym poczatku. Tylko po co obciazac serwer

Czyli pobranie czasu, a następnie po wyjściu wrzucenie go do bazy jest obciążeniem większym niż timery? Weź się uderz w głowę. 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Już sobie poradziłem( z pomocą  ¥), dzięki wszystkim za pomoc. Okazało się to bardzo łatwe do zrobienia, myślałem, że trzeba zrobić to inaczej. :)

Temat do zamknięcia.

Edytowane przez Mario

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
3 godziny temu, Frank napisał:

Czyli pobranie czasu, a następnie po wyjściu wrzucenie go do bazy jest obciążeniem większym niż timery? Weź się uderz w głowę. 

Timery nie są żadnym obciążeniem, tylko kod który w nich jest.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Gość
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.

  • Przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

×