InSim
InSim jest protokołem, który pozwala zewnętrznemu programowi komunikować się z Live For Speed. Pozwala na tworzenie połączenia z grą oraz wysyłanie i odbieranie pakietów danych. Protokół InSim opisuje sposób formatowania każdego z tych pakietów, a każdy język programowania, który może utworzyć połączenie sieciowe i wysyłać i odbierać ciągi danych binarnych, może się z nim łączyć.
oficjalna dokumentacja znajduje się w pliku InSim.txt, znaleziony w folderze games doc. Składa się z pliku nagłówkowego C++, który zawiera definicję każdego pakietu, a także komentarze Scawena dotyczące tego, jak każdy z nich powinien być używany. Niniejsza dokumentacja jest przeznaczona jako pomocnicza dla tego pliku.
UDP vs TCP
InSim obsługuje zarówno połączenia UDP, jak i TCP. W trybie UDP można nawiązać tylko jedno połączenie, jednak do gry można nawiązać do ośmiu połączeń w TCP. Niezależnie od tego, czy jest podłączony w TCP, czy UDP, można określić oddzielne gniazdo UDP do odbierania aktualizacji pozycji samochodu, takie jak IS_MCI i IS_NLP.
przykład InSim
sposób tworzenia połączenia InSim jest oczywiście zależny od języka programowania, którego używasz, ale tutaj podejmujemy próbę udokumentowania procesu za pomocą przykładów z popularnego języka programowania Python. Jak wspomniano powyżej, każdy język zdolny do połączenia z gniazdem może być użyty do interfejsu z LFS, jednak zasada pozostaje taka sama niezależnie od tego.
Tworzenie połączenia
przede wszystkim musimy ustanowić połączenie gniazda z grą, w tym przypadku w TCP.
# Import Python's socket module.import socket# Initialise the socket in TCP mode. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# Connect to LFS.sock.connect(('localhost', 29999))
Inicjalizacja InSim
po nawiązaniu połączenia musimy zainicjować system InSim wysyłając pakiet IS_ISI. Zanim jednak to zrobimy, musimy najpierw intitailse InSim w samym LFS. Aby to zrobić, uruchom grę i wprowadź komendę czatu „/ insim 29999”. Użyty numer portu może być dowolnym poprawnym portem, ale 29999 zazwyczaj jest akceptowanym domyślnym.
oto definicja pakietu IS_ISI z InSim.txt.
struct IS_ISI // InSim Init - packet to initialise the InSim system{byteSize;// 44byteType;// ISP_ISIbyteReqI;// If non-zero LFS will send an IS_VER packetbyteZero;// 0wordUDPPort;// Port for UDP replies from LFS (0 to 65535)wordFlags;// Bit flags for options (see below)byteSp0;// 0bytePrefix;// Special host message prefix characterwordInterval;// Time in ms between NLP or MCI (0 = none)charAdmin;// Admin password (if set in LFS)charIName;// A short name for your program};
każdy pakiet InSim zaczyna się nagłówkiem, składającym się z 4 bajtów. Pierwszy bajt to Rozmiar pakietu, następnie typ pakietu z wyliczenia ISP_, a następnie ReqI (skrót od Request Id). Za każdym razem, gdy żądanie jest wysyłane do LFS, wartość ReqI musi być ustawiona na niezerową, przy czym LFS odpowie z tą samą wartością ustawioną w ReqI żądanego pakietu. Wreszcie czwarty bajt różni się w zależności od typu danego pakietu, który w tym przypadku jest pusty.
jak widać pakiet IS_ISI zawiera różne opcje i flagi, które są używane podczas inicjalizacji systemu InSim. Musimy spakować te dane do binarnego sformatowanego ciągu znaków, aby wysłać je do LFS.
# Import Python's struct module, which allows us to pack and unpack strings.import struct# Pack the IS_ISI data into a string.isi = struct.pack('BBBBHHBcH16s16s', 44, # Size 1, # Type 1, # ReqI 0, # Zero 0, # UDPPort 0, # Flags 0, # Sp0 ' ', # Prefix 0, # Interval 'password', # Admin 'MyProgram',) # IName# Send the string to InSimsock.send(isi)
odbieranie danych
po utworzeniu połączenia i zainicjowaniu InSim musimy ustawić pętlę odbioru pakietów. Ponieważ dane w trybie TCP są wysyłane jako stały strumień Danych, wiele pakietów może dotrzeć w jednym wywołaniu odbiorczym, a niektóre pakiety mogą dotrzeć niekompletne. Oznacza to, że musimy przechowywać wszystkie przychodzące dane w buforze, a następnie odczytywać każdy pakiet, gdy jesteśmy pewni, że jest kompletny.
# We use a string as the buffer.buffer = ''while True: # Receive up to 1024 bytes of data. data = sock.recv(1024) # If no data is received the connection has closed. if data: # Append received data onto the buffer. buffer += data # Loop through each completed packet in the buffer. The first byte of # each packet is the packet size, so check that the length of the # buffer is at least the size of the first packet. while len(buffer) > 0 and len(buffer) > ord(buffer): # Copy the packet from the buffer. packet = buffer)] # Remove the packet from the buffer. buffer = buffer):] # The packet is now complete! :) # doSomethingWithPacket(packet) else: break# Release the socket.sock.close()
rozpakowywanie pakietów
po otrzymaniu danych pakietu jako binarnego sformatowanego ciągu znaków, musimy rozpakować te dane do formatu, który jest dla nas przydatny. W poprzednim przykładzie, kiedy wysłaliśmy pakiet inicjalizacji IS_ISI, ustawiliśmy ReqI na niezerową, co oznacza, że LFS odpowiedział pakietem w wersji IS_VER, jednak nic z nim nie zrobiliśmy. Najpierw przyjrzyjmy się definicji pakietu IS_VER z InSim.txt.
struct IS_VER // VERsion{byteSize;// 20byteType;// ISP_VERSIONbyteReqI;// ReqI as received in the request packetbyteZero;charVersion;// LFS version, e.g. 0.3GcharProduct;// Product : DEMO or S1wordInSimVer;// InSim Version : increased when InSim packets change};
teraz spójrzmy, jak rozpakowalibyśmy te dane w Pythonie.
# Import Python's struct module.import struct# Unpack the binary formatted packet data into the values we need.size, type, reqi, zero, version, product, insimver = struct.unpack('BBBB8s6sH', packet)# Check the InSim version.if insimver != 4: print 'Invalid InSim version!' sock.close()
Keep Alive
aby utrzymać otwarte połączenie, LFS wyśle pakiet „keep alive” co około 30 sekund. Pakiet ten jest pakietem IS_TINY z podtypem TINY_NONE. Musimy odpowiadać na ten pakiet za każdym razem, gdy jest on odbierany, aby zapobiec przerwaniu połączenia z InSim.
# Some constants.ISP_TINY = 3TINY_NONE = 0# Check the packet type.if ord(packet) == ISP_TINY: # Unpack the packet data. tiny = struct.unpack('BBBB', packet) # Check the SubT. if tiny == TINY_NONE: # Send the keep alive packet back to LFS. sock.send(packet)
dalsze przykłady
możesz zobaczyć pełny przykład tego kodu, a także inne na stronie przykładów InSim.
Biblioteki InSim
oczywiście, jak mówi stare przysłowie, nie powinieneś próbować odkrywać koła na nowo (chyba że próbujesz dowiedzieć się więcej o kołach) i istnieje kilka dojrzałych bibliotek InSim dostępnych do użycia we własnym kodzie.
Biblioteki InSim | ||||
---|---|---|---|---|
Biblioteka | Platforma | Licencja | web | |
LFSLib | . NET Framework | GPL | strona projektu | |
LFS_External | .NET Framework | Freeware | wątek lfsforum | |
JInSim | Java | Mozilla | wątek lfsforum | |
pyinsim | Python | LGPL | wątek lfsforum | |
CInSim | C / C++ | Freeware | wątek lfsforum | |
phplfs | PHP5 | Licencja Apache V2.0 | strona projektu | |
PRISM | PHP7 | MIT | sekcja lfsforum | |
InSim.NET | . NET Framework | LGPL | wątek lfsforum |
Insim Reference
oto próba odniesienia się do pełnego protokołu InSim.
numer pakietu | ||
---|---|---|
Pakiet | opis | Typ |
Inicjalizacja | ||
IS_ISI | inicjalizacja InSim | Instrukcja |
ogólnego przeznaczenia | ||
IS_TINY | Pakiet 4-bajtowy ogólnego przeznaczenia | oba |
IS_SMALL | Pakiet 8 bajtowy ogólnego przeznaczenia | oba |
Prośba o wersję | ||
IS_VER | informacje o wersji | Info |
raportowanie stanu i wnioski | ||
IS_STA | wysyłana za każdym razem, gdy zmienia się stan gry | Info |
IS_SFP | Wyślij, aby ustawić różne opcje stanu | Instrukcja |
tryb ekranu | ||
IS_MOD | Wyślij, aby zmienić tryb ekranu | Instrukcja |
wiadomości tekstowe i naciśnięcia klawiszy | ||
IS_MSO | wiadomości systemowe i użytkownika wysyłane z LFS | informacje |
IS_III | wiadomości użytkownika do hosta InSim | Info |
IS_MST | Wyślij LFS wiadomość lub polecenie (64 znaki) | Instrukcja |
Is_msx | rozszerzona wersja IS_MST (96 znaków), nie dla poleceń | Instrukcja |
IS_MSL | Wyślij wiadomość do lokalnego klienta gry | Instrukcja |
IS_MTC | Wyślij wiadomość do konkretnego połączenia lub odtwarzacza | Instrukcja |
IS_SCH | Wyślij pojedynczy znak lub klawisz naciśnij | Instrukcja |
powiadomienie Multiplayer | ||
IS_ISM | wysyłany podczas uruchamiania lub dołączania do hosta | Info |
IS_NCI | wysłane po ustawieniu hasła administratora hosta, zawiera dane IP użytkownika i języka | Info |
głosuj powiadom | ||
IS_VTN | Powiadom o głosowaniu zawodników (restart wyścigu, Kwalifikacje itp.. | Info |
śledzenie wyścigu | ||
IS_RST | Start lub wznowienie wyścigu | Info |
IS_NCN | nowe połączenie z serwerem | Info |
IS_SLC | aby zgłosić zmiany stanu samochodu (obecnie start lub stop) | Info |
IS_CSC | zgłasza aktualnie wybrany samochód | Info |
IS_CNL | połączenie z serwerem | Info |
IS_CPR | zmiana nazwy gracza | Info |
IS_NPL | nowy gracz dołącza do wyścigu lub opuszcza pity | Info |
IS_PLP | pity graczy (gone to garage screen) | Info |
IS_PLL | zawodnik opuścił wyścig (odszedł do spectate) | Info |
IS_CRS | reset samochodu (wciśnięty spacja) | Info |
IS_JRR | może być używany do resetowania lub uruchamiania samochodu w określonej lokalizacji | Instrukcja |
IS_LAP | czas okrążenia ukończony | Info |
IS_SPX | Info | |
IS_PIT | ruszył Pit stop (przy pit boxie) | Info |
IS_PSF | pit stop zakończony | Info |
IS_PLA | zawodnik wszedł na pit lane (do pit lub służyć karnie) | Info |
is_chh | zmieniono widok kamery (widok pościgu, widok niestandardowy itp.. | Info |
IS_PEN | kara podana lub wybita | Info |
IS_TOC | gracz przejal inny samochod(Zamiana kierowcy) | Info |
IS_FLG | pokazana flaga gracza (żółta lub niebieska) | Info |
is_pfl | zmieniono flagi graczy (auto-biegi, auto-sprzęgło itp.. | Info |
IS_FIN | zawodnik ukończył wyścig (przekroczył linię mety) | Info |
IS_RES | wynik zawodnika przyznany, potwierdzony koniec | Info |
IS_REO | Zmień kolejność | oba |
Autocross | ||
IS_AXI | autocross layout loaded | Info |
IS_AXO | gracz uderzył w obiekt autocross | Info |
IS_OCO | można użyć do nadpisania określonych lub wszystkie światła startowe | Instrukcja |
IS_UCO | wysyła informacje o insim i okręgach | Info |
śledzenie samochodów | ||
IS_NLP | aktualna pozycja zawodnika, okrążenia i wyścigu | Info |
IS_MCI | bardziej szczegółowa wersja IS_NLP, współrzędne świata, prędkość, kąt i kierunek | Info |
sterowanie kamerą | ||
IS_SCC | Ustaw oglądany samochód i wybierz kamerę | Instrukcja |
IS_CPP | Ustaw pełną pozycję kamery | Instrukcja |
Kontrola powtórek | ||
IS_RIP | załaduj powtórkę i przejdź do określonego miejsca docelowego | Instrukcja |
zrzuty ekranu | ||
IS_SSH | Zrób zrzut ekranu | Instrukcja |
przyciski InSim | ||
IS_BFN | Usuń przycisk lub wszystkie przyciski | Instrukcja |
IS_BTN | Wyślij przycisk na ekran | Instrukcja |
IS_BTC | wysyłane po kliknięciu przycisku | Info |
IS_BTT | wysłane po wpisaniu tekstu | Info |