Skocz do zawartości

oLuju

Użytkownicy
  • Postów

    44
  • Dołączył

  • Ostatnia wizyta

O oLuju

  • Urodziny 13.07.1999

O mnie

  • Płeć
    Male

Osiągnięcia oLuju

Chicken

Chicken (1/13)

0

Reputacja

  1. Postać innego użytkownika nie porusza się płynnie - zamiast sunąć po ziemi lekko skacze w danym kierunku. Ping to stabilne 63ms. Typ połączenia to TCP. Generalnie nie są to duże skoki i da się to przeżyć, jednak chciałbym upłynnić ten ruch w 100%. Nie mam jednak pomysłu jak - myślałem nad przechowywaniem kilku pakietów (np. 3) w tablicy i wedle zawartych w nich danych tworzyć ścieżkę po której poruszałoby się widmo innego gracza. Niestety tworzyłoby to dodatkowe opóźnienie bo skrypt czekałby nie na 1 a na kilka pakietów by poruszyć danym obiektem. EDIT: Wygląda to mniej więcej tak:
  2. Przez ostatni rok doszkalałem się w pisaniu gier Multiplayer w GM. Po tak długim czasie udało mi się napisać server dedykowany w JS. Wszystko śmiga: kolejka, lobby, przesyłanie danych. O ile w sieci lokalnej (gdy server działał na Raspberry Pi'u) nie było żadnych odczuwalnych lagów to tak po przerzuceniu plików na zewnętrzny hosting (DigitalOcean) pojawiły się drobne ściny. Czy ma ktoś może jakieś pomysły co gra (lokalnie) mogłaby robić by "zamaskować" lekką desynchronizację? Server korzysta tylko z biblioteki 'net' - jeśli to ona może negatywnie wpływać na jakość połączenia, dajcie znać.
  3. Ta wiem, że z tym szyfrowaniem lipton straszny i to jest niezbędne. Co do http_requesta to widziałem że ten pozwala na użycie POST'a ale widząc przykład w dokumentacji trochę mi się to odwidziało, ale będę musiał tego spróbować. No ale bez tej funkcji z 1 konta jest w stanie korzystać niezliczona ilość osób. Co innego gdyby baza danych była w stanie załóżmy po 10 minutach automatycznie "wylogować" gracza jeśli ten nie pobiera/wysyła żadnych danych (coś w rodzaju timeout'a). Generalnie próbowałem szukać sposobu by działało to tak ja w przeglądarce, czyli np.: w sesjach. Gracz loguje się, jest połączony z bazą danych (jest w stanie odczytywać/zapisywać w niej dane [oczywiście tylko w obrębie swojego profilu/konta]), może się wylogować albo jeśli przez pewien czas nie będzie nic robił (idle) automatycznie go lognie (timeout).
  4. Większość problemów w mojej multiplayer'owej grze mam już za sobą. Postanowiłem teraz zaimplementować system odpowiedzialny za logowanie się na serwery gry a następnie pobieranie danych odnośnie danego gracza. Udało mi się to i działa bez najmniejszego zarzutu i teraz pewnie ktoś zada pytanie po co w takim razie o tym pisze, otóż z tego co wiem to sposób w jaki to zrobiłem nie należy do najbezpieczniejszych. Chciałbym poradzić się czy jednak to wystarczy a jak nie to jakie zabezpieczenia można byłoby dodać. Skrypt wygląda tak: Create: login = get_string("Podaj login:", "login"); password = get_string("Podaj haslo:", "password"); get = http_get("http://mojastrona.pl/logon.php?login=" + login + "&password=" + password + "&alrd_logged=1"); Async Event - HTTP: ///Czekanie na odebranie danych { if ds_map_find_value(async_load, "id") == get { if ds_map_find_value(async_load, "status") == 0 { r_str = ds_map_find_value(async_load, "result"); alarm[0]=5 } else { r_str = "null"; } } } Alarm 0: ///Odczytywanie odebranych danych z Bazy Danych (DataBase) if string_pos("Login: ", r_str) != 0 { login = string_copy(r_str, string_pos("Login: ", r_str)+7, ((string_pos("LOGIN_END", r_str))-(string_pos("Login: ", r_str))-7) ); //string_insert(name, text, string_pos(",", text)); } if string_pos("alrd_logged: ", r_str) != 0 { alrd_logged = string_digits(string_copy(r_str, string_pos("alrd_logged: ", r_str)+13, ((string_pos("ALRD_LOGGED_END", r_str))-(string_pos("alrd_logged: ", r_str))-13) )); if ( alrd_logged == "1" ) { imowner = 0 show_message("Uzytkownik aktualnie zalogowany!") game_restart() exit; } else { imowner = 1 } } if string_pos("Rank: ", r_str) != 0 { rank = string_copy(r_str, string_pos("Rank: ", r_str)+6, ((string_pos("RANK_END", r_str))-(string_pos("Rank: ", r_str))-6) ); //string_insert(name, text, string_pos(",", text)); } Wytłumaczę teraz trochę jak to działa. W Creat'ie prosi się użytkownika o wpisanie Loginu i Hasła, a następnie to jest wysyłane na stronę gdzie odbywa się weryfikacja i wysłanie danych. Odpowiednie dane odczytywane są z bazy i wyświetlane w takiej postaci: Logowanie udane! Login: Gracz1LOGIN_END [...] Gdy dane dojdą skrypt w Alarmie zajmuje się znalezieniem odpowiednich wartości i zapisaniu ich w zmiennych. Niestety korzystam z darmowego hostingu na którym są reklamy, a ich kod html znajduje się w Result'ie. Wiem, że można użyć JSON'a bo sam GM ma do tego specjalne komendy i jest to prostsze ale chyba tylko w przypadku gdy result zawiera wyłącznie kawałek tego JSON'a (bez śmieci takich jak reklamy). Kod szuka pozycji startowej danej wartości np.: loginu, potem szuka końca który oznaczony jest napisem: "COSTAM_END" i wyznacza pozycje którą ma skopiować do zmiennej. Teraz co to jest "alrd_logged" - zmienna, która mówi o tym czy użytkownik jest aktualnie zalogowany (korzysta ze swojego konta). Na początku podczas logowania na stronę wysyłana jest zmienna alrd_logged=1 że gracz się loguje i jeśli w result'ie "alrd_logged" z bazy danych ma już wartość 1 traktujemy to tak że ktoś już korzysta z konta i nie można się do niego zalogować. Gdy wyłączymy grę jest taki kod: (Game end) i (Press 'Escape'): ///Wyloguj mnie if ( imowner == 1 ) { show_message("Wylogowywuje sie...") http_get("http://mojastrona.pl/logon.php?login=" + login + "&password=" + password + "&alrd_logged=0"); show_message("Pomyslnie wylogowano!!!") } else { //probowalem zalogowac sie na czyjesc konto } imowner to zmienna pomocnicza która jest równa 1 jeśli pomyślnie zalogowaliśmy się na konto - jest to zabezpieczenie przed tym by w momencie gdy "włamywacz" zna passy do konta prawdziwego właściciela to w momencie wyjścia z gry ta nie wysłała informacji o wylogowanie się (nie ustawiła alrd_logged na 0 - tak jakby nikt nie był zalogowany). Sama strona internetowa (logon.php) czyta GET'a tak: 1.Sprawdzanie poprawności loginu i hasła - czy istnieją w bazie danych 2.Jeśli tak wysyłanie informacji o użytkowniku 3.Jeśli strona otrzyma alrd_logged=1 tak też ustawi w bazie danych (a jeśli 0 to analogicznie ustali 0 w bazie danych). Są 2 "dziury": 1.Potencjalny włamywacz odbiera zawsze w result'ie wszystkie dane o użytkowniku, tylko że alarm na samym starcie przed "przesianiem i posegregowaniem" zmiennych z tego co przyszło sprawdza alrd_logged z strony i jak jest 0 to kontynuuje, a jak nie (czyli 1) to zatrzymuje się, wywala komunikat o tym że ktoś już korzysta z konta i restartuje grę (na razie w ramach testu, oczywiście). 2. Przy próbie logowania na server wysyłamy zmienną alrd_logged=1 a co za tym idzie ponownie ustalamy ją na 1 w samej bazie danych. W przypadku jak ktoś już korzysta z konta nie wprowadza to tak naprawdę żadnej zmiany. Te 2 niedociągnięcia nie wydają mi się jakoś zbyt niebezpieczne więc ich nie poprawiałem, jednak problem leży w samym request'ie (żądaniu) wysyłanym na stronę, gdyż nasz Login i Hasło idzie zupełnie "gołe" , a nie zabezpieczone (zahashowane lub inaczej zaszyfrowane [jednak nie mam pojęcia jak by to zrobić]). Macie jakieś pomysły co zmienić, ulepszyć bądź dodać???
  5. Problemu z Firewall'em nie miałem. Jedynie co, to Avast pokazywał okienko mówiące o tym, że plik może być niebezpieczny. Kaspersky za to już problemu nie widział. Powyłączałem osłony antywirusów ale to nic nie dało. Najlepszym wyjściem byłoby założenie servera dedykowanego, jednak z tego co wiem to do GM'a ciężko jest coś takiego zrobić. Zostaje jeszcze stare, dobre Hamachi.
  6. Taaa, pingują się. A może to coś mieć związek z portem?
  7. 1 ma: 192.168.0.100 2 ma: 192.168.0.101 Uwierz mi, że próbowałem wszelkich kombinacji i żadna nie działała.
  8. Hej, otóż mam już w pełni funkcjonujący projekt gry z jednym małym problemem. Otóż, gdy włączam Server i 2 Clientów na tym samym komputerze (server tworzony albo na IP: 127.0.0.1 lub 192.168.0.100 [ip mojego komputera w sieci LAN]) wszystko funkcjonuje normalnie. Za to: zakładając server i 1 clienta na pierwszym komputerze ci łączą się normalnie, 2 klient na drugim komputerze w tej samej sieci LAN już nie może. Próbowałem różnych kombinacji z IP: 192.168.0.100 <--- IP komputera na którym stawiam Server IP na jakim tworzony jest Server | IP do którego łączy się Client -----------------------------------------|---------------------------------------- 127.0.0.1 | 127.0.0.1 -----------------------------------------|---------------------------------------- 127.0.0.1 | 192.168.0.100 -----------------------------------------|---------------------------------------- 192.168.0.100 | 192.168.0.100 -----------------------------------------|---------------------------------------- 192.168.0.100 | 127.0.0.1 Port: 9000 Typ połączenia: socket_tcp Maksymalna ilość graczy: 20 Macie jakiś pomysł o co może chodzić???
  9. Tylko, że ja właśnie robię "zwykłe" połączenie. W szczególności, że nie używam tego: network_set_config(network_config_connect_timeout, 1000); network_set_config(network_config_use_non_blocking_socket, 1); Z ciekawości dopisałem to w Creacie swojego oServer'a i nie zależnie czy jest: network_set_config(network_config_use_non_blocking_socket, 1); lub: network_set_config(network_config_use_non_blocking_socket, 0); nie powoduje to żadnego wpływu na wysyłane dane - gracze poruszają się po staremu i wszystko funkcjonuje normalnie. Wysyłanie danych z Servera za pomocą bufora: "server_buffer" jak nie działało tak nie działa dalej. Przejrzałem też twój projekt, problemem jest odmienny "styl napisanego skryptu" przez co jest mi się trochę trudno połapać o co chodzi. Próbowałem też wysyłania danych surowych i skompresowanych, lecz to również nie przyniosło żadnego efektu. Nie pojmuje tego błędu - jakim prawem dane nie są wysyłane skoro wszystko działa dokładnie tak samo jak pierwszy buffer odpowiedzialny za wysyłanie informacji pomiędzy klientami. Jedyną różnicą jest to że dane wysyłane są z bezpośrednio z Servera do Clientów, a nie: od Clienta do Servera, a stamtąd do innych użytkowników (Clientów). EDIT: Okej, udało mi się rozwiązać problem. Nie wiem jakim cudem. Generalnie pokombinowałem jeszcze z kolejnością wysyłania zmiennych i odczytywaniem nazw bufferów. Grunt, że działa.
  10. Hej, otóż udało mi się ogarnąć Networking w GMS'ie, jednak natknąłem się na pewien błąd, którego nie potrafię rozwiązać. Otóż oprócz posiadania podstawowego buffer'a do wysyłania danych na temat pozycji graczy potrzebuje utworzyć 2 odpowiedzialny za wysyłanie danych z Servera do Clientów. Bufferem tym wysyłane są dane nad którymi kontrolę ma tylko server (np.: aktualny czas rozgrzewki, kiedy rozpocząć kolejną rundę, kiedy zakończyć/rozpocząć mecz [rozpocząć po rozgrzewce]). Wygląda to tak: nazwa obiektu - nazwa zdarzenia oServer - Networking: switch(async_load[? "type"]){ case network_type_connect: case network_type_non_blocking_connect: server_handle_connect(async_load[? "socket"]); break; case network_type_data: server_handle_message(async_load[? "id"], async_load[? "buffer"]); break; case network_type_disconnect: server_handle_disconnect(async_load[? "socket"]); break; } Script - server_create: server_buffer = buffer_create(128, buffer_fixed, 1); Script - server_handle_message: var socket_id = argument0, buffer = argument1, client_id_current = clientmap[? string(socket_id)].client_id; buffer_seek(server_buffer, buffer_seek_start, 0); buffer_write(server_buffer, buffer_u16, match_end); buffer_write(server_buffer, buffer_u16, warmuptime); buffer_write(server_buffer, buffer_u16, global.matchstart); with(oServerClient){ if(client_id != client_id_current){ network_send_raw(self.socket_id, other.server_buffer, buffer_tell(other.server_buffer)); //self and other }} oClient - Networking: switch(async_load[? "type"]){ case network_type_data: client_handle_message(async_load[? "buffer"]); break; } Script - client_connect: server_buffer = buffer_create(128, buffer_fixed, 1); Script - client_handle_message: var buffer = argument0; buffer_seek(server_buffer, buffer_seek_start, 0); match_end = buffer_read(server_buffer, buffer_u16); warmuptime = buffer_read(server_buffer, buffer_u16); global.matchstart = buffer_read(server_buffer, buffer_u16); oPlayer.match_end = match_end oPlayer.warmuptime = warmuptime //global.matchstart = matchstart próbowałem jeszcze tak (bez "server_buffer = buffer_create..." w skrypcie "client_connect"): var buffer = argument0; buffer_seek(buffer, buffer_seek_start, 0); match_end = buffer_read(buffer, buffer_u16); warmuptime = buffer_read(buffer, buffer_u16); global.matchstart = buffer_read(buffer, buffer_u16); oPlayer.match_end = match_end oPlayer.warmuptime = warmuptime //global.matchstart = matchstart Nie działa. Gracze nie otrzymują danych na temat zmiennych pomimo tego, że server poprawnie je kontroluje (np.: po zakończeniu rozgrzewki ustala zmienną odpowiedzialną za start meczu na 1). Gdy do gry dołączy pierwszy gracz nic się nie dzieje - zmiennych nie odczytuje, ale można się poruszać po mapie. Gdy do gry dołączy drugi gracz czasem od razu, a czasem po pewnym czasie wywala takiego errora: ___________________________________________ ############################################################################################ ERROR in action number 1 of Async Event: Networking for object oClient: Attempting to read from outside the buffer, returning 0 at gml_Script_client_handle_message ############################################################################################ -------------------------------------------------------------------------------------------- stack frame is gml_Script_client_handle_message (line 0) gml_Object_oClient_Other_68 Wie ktoś co może robię źle? Mi skończyły się już pomysły co do tego jak rozwiązać ten problem.
  11. Hej, otóż po tym jak przeniosłem się na GMS'a z 8.1 postanowiłem spróbować stworzyć jakąś grę multiplayer. W poprzedniej wersji używało się mplay'a , którego działanie byłem w stanie zrozumieć. Niestety w najnowszym GM'ie tworzenie połączeń, wysyłanie i odbieranie danych to dla mnie kosmos. Czytałem dokumentację oraz ten tutorial: https://help.yoyogames.com/hc/en-us/articles/216754698-Networking-Overview i z tego co widzę teraz trzeba używać ds_map do przechowywania danych. Próbowałem Demo z tego tutorialu trochę przerobić i działa to tak sobie. Nie wiele z tego rozumiem - znacie jakieś inne poradniki tłumaczące działanie funkcji Networkingu w GMS'ie?
  12. OK udało mi się wszystko w miarę naprawić. Gdy gracze Teamu 1 strzelają to pociski pojawiają się normalnie. Jednak teraz jest inny problem, bo strzelanie nie działa w Teamie 2: Pocisk u gracza strzelającego (z teamu 2) pojawia się normalnie, za to u innych nie ma po nim śladu. Kod strzelania dla gracza 1 z teamu 1: GML //===================JESLI JESTEM KIMS INNYM========================== while mplay_message_receive(0) { if mplay_message_id() == 100 and mplay_message_value() == 1 { mplay_message_send(0, 100, 0); instance_create(self.x, self.y, obj_pocisk1_team1); } } //=====================JESLI NIM JESTEM============================== if mouse_check_button(mb_left) { if przeladuj=0 { if magazynek>0 { if strzelac=1 { strzelac=0 instance_create(self.x, self.y, obj_pocisk1_team1) mplay_message_send(0, 100, 1); mplay_data_write(4,obj_pocisk1_team1.x); mplay_data_write(5,obj_pocisk1_team1.y); magazynek-=1 alarm[1]=20 } } } } Kod strzelania dla gracza 1 z teamu 2: GML //===================JESLI JESTEM KIMS INNYM========================== while mplay_message_receive(0) { if mplay_message_id() == 103 and mplay_message_value() == 1 { mplay_message_send(0, 103, 0); instance_create(self.x, self.y, obj_pocisk1_team2); } } //=====================JESLI NIM JESTEM============================== if mouse_check_button(mb_left) { if przeladuj=0 { if magazynek>0 { if strzelac=1 { strzelac=0 instance_create(self.x, self.y, obj_pocisk1_team2) mplay_message_send(0, 103, 1); mplay_data_write(22,obj_pocisk1_team2.x); mplay_data_write(23,obj_pocisk1_team2.y); magazynek-=1 alarm[1]=50 } } } } Przewertowałem cały kod i wszytko jest dokładnie tak samo u każdego gracza, wszystkie ID się zgadzają. Chce dokończyć ten projekt do końca i tyle (nie lubię porzucać niedokończonych projektów). Zacząłem już szukać GM'a Studio. Więc prawdopodobnie niedługo się na niego przeniosę. I am Lord - Jeśli faktycznie mój post umrze bo NIKT tego nie pamięta to dam se spokój <_<
  13. Odbiorca dostaje wiadomość o stworzeniu pocisku i tworzy go u siebie. Wydaje mi się że korekcja nie istnieje, bo jeśli pocisk zostanie utworzony u wszystkich graczy w tej samej pozycji, nada mu sie kieeunek i szybkość to dalej już poleci tak samo u wszystkich. Manual, który czytałem opisywał używanie mplay'a na przykładzie ponga. Piłka w tej grze nie dostaje caly czas informacji o jej pozycji bo przez zgubione pakiety (bądź opóźnione) teleportowała by się, dlatego wszystkie dane (pozycja, szybkosc, kierunek) wysyłane są tylko gdy piłkę uderzy deska, a później wysyła tylko część info (kierunek, szybkość) którą ustala raz. Pomyślałem że podobnie będzie w przypadku pocisku, bo gdy będzie ich dużo i zaczną co ,np. 1s. wysyłać swoją pozycję by zrobić korektę gdzie się znajdują to przez to ze na mapie bedzie kilka pocisków tego samego gracza, zaczną teleportować się do siebie na wzajem. Ponadto gracze nie wysyłaliby aż tyle danych. Co do buffera to nie. Dane o ID 1 są wysyłane, a następnie odbierane, tyle. Co prawda informacja o stworzeniu pocisku to tak zwany Message, a nie Data shared jak wszystko i nie wiem czy gdy mplay_message wysyła pakiet, to gdy go ktoś odbierze zobaczy go jako 'pojedyńczy impuls' czy potraktuje jak zmienną z wartością true przez co faktycznie tworzy ciągle nowe pociski.
  14. Próbowałem się przerzucić na GMS'a ale przez kilka zmian w GML'u oraz kilka ogólnikowych "usprawnień"/zmian wydaje mi sie on trochę toporny i nie mogłem się przyzwyczaić. Co do odpowiedzi - nie to nie to, pocisk tworzy dany gracz po naciśnięciu LPM i wysyła informacje gdzie utworzyć ten że pocisk (w miejscu gdzie aktualnie się znajduję gracz), a pocisk wysyła informacje o szybkości i kierunku (gdzie u innych graczy po prostu pobiera te dane). Sam zapomniałem też wspomnieć o 2 rzeczach: 1.Problem nie leży w złym ustawieniu szybkości strzelania, bo pociski wystrzeliwane są co 20 kroków. 2.Gracz który strzel widzi swoje pociski normalnie, tylko reszta ma je "zbugowane".
  15. Hej, otóż ostatnio przeczytałem sobie manual tłumaczący zasadę działania multiplayer'a w GM 8.1. Udało mi się stworzyć prototyp w którym jest 6 ludzików (graczy) 3 w drużynie niebieskiej i 3 w drużynie czerwonej. System przydzielający nowego gracza do danego ludzika w grze działa, komunikowanie z serwerem i synchronizacja "prawie" też. Prawie ponieważ napotkałem pewną trudność, której nie potrafię rozwiązać. Otóż postacie te mogą strzelać. Generalnie wygląda to tak że każdy ludzik jest innym objectem (player1, player2, etc.) tak jak ich pociski (bullet1, bullet2, etc.). Niestety problem pojawia się w momencie strzału, gdyż trzeba wysłać wiadomość na serwer, która stworzy ten pocisk u wszystkich innych graczy. Generalnie udało mi się to ale niestety po strzale następuje dłuuuuuuga linia tego pocisku bez końca. Generalnie wygląda to tak (jak coś jest to obraz z widoku gracza 1, ludzik który strzela to gracz 2): Pocisk w Creat'ie zawiera taki kod: GML ///Kontrola kierunku strzalu i szybkosci pocisku if global.nextplayer != 1 //Definiowanie ID gracza (gracz1, gracz,2) { //Jesli nie x = mplay_data_read(4); //Pobierz pozycje x y = mplay_data_read(5); //Pobierz pozycje y speed = mplay_data_read(6); //Pobierz szybkosc objektu direction = mplay_data_read(7); //Pobierz kierunek obiektu exit; } else {//Jesli tak direction=point_direction(x,y,mouse_x,mouse_y); //Wez kierunek lotu z pozycji myszki speed=15 //Ustal szybkosc mplay_data_write(6,obj_pocisk1_team1.speed); //Wyslij dane o szybkosci pocisku mplay_data_write(7,obj_pocisk1_team1.direction); //Wyslij dane o kierunku pocisku } Kod wystrzału wygląda tak: GML if global.nextplayer != 1 { //Jesli nie y = mplay_data_read(2); //Pobierz pozycje gracza x x = mplay_data_read(3); //Pobierz pozycje gracza y image_single = mplay_data_read(38); //Pobierz kierunek gdzie patrzy sie gracz while mplay_message_receive(0); //Gdy zostanie odebrana wiadomosc... { if (mplay_message_id() == 100) instance_create(self.x, self.y, obj_pocisk1_team1); //Jesli to wiadomosc o ID=100 stworz obiekt pocisku } exit; } else { if mouse_check_button(mb_left) { if przeladuj=0 { if magazynek>0 { if strzelac=1 { strzelac=0 instance_create(self.x, self.y, obj_pocisk1_team1) //Stworz obiekt u siebie mplay_message_send(0, 100, obj_pocisk1_team1); //Wyslij wiadomosc o wystrzale do innych mplay_data_write(4,obj_pocisk1_team1.x); //Wyslij pozycje x , gdzie stworzyl sie pocisk mplay_data_write(5,obj_pocisk1_team1.y); //Wyslij pozycje y , gdzie stworzyl sie pocisk magazynek-=1 alarm[1]=20 } } } } } Zaznaczam też że większość kodu uciąłem żeby nie zawalać posta. Reszta działa i jedynym problemem jest ten duplikujący się pocisk. Jakieś pomysły jak to poprawić lub zrobić to lepiej???
×
×
  • Dodaj nową pozycję...