-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cross-platform plugin on TCP #91
base: dev
Are you sure you want to change the base?
Conversation
I will probably make some tests today/tomorrow to check the performance of the implementation. On first view I had again some problems with TCP, but I think when the performance is fine it allows some feature to build much faster than with shared memory. In addition, I think it makes the development of other clients simpler. That means a lot of plus points for TCP if the performance is right. |
I've also considered using UDP instead of TCP, but it would be too unreliable and you could lose important events |
Performance seems to be ok. Also, I have some ideas for better performance, so that should not be such a problem. 2 other things are more of a problem:
|
I'll look into that |
…nto RenCloud-master
Ren cloud master
Doesn't require to manually include source and header files
Log when finishing accepting thread would cause the game to crash because it would try to access the game log after it has been disposed. Made it so the destructor waits for the accepting thread to finish.
Fixed the issue with crash on |
I was able to build a plugin for mac os with minor edits in the code. The game itself runs, but I don't really understand where I should look at the telemetry readings. When I access 0.0.0.0:45454 I get |
Well, the listening on Regarding |
If you don't mind, send a sample, in Python, for example |
The code for receiving data in Python would look something like this: import socket # import the socket library
def main():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: # create the socket object with the Internet address family (IPv4) and stream socket type
s.connect(("127.0.0.1", 45454)) # connect to the plugin listener
while True:
data = s.recv(1024) # receive the bytes
print(data) # print the bytes
if __name__ == '__main__':
main()
I'd love to, I don't have any Apple device myself so it would be really useful for me |
NOTE: Marked the PR as draft since it's not 100% finished and there's still room for improvement |
Yes, we almost synchronously managed to write the code to get the data :D |
Exactly, except that every "message" is prefixed with a 4 byte (Int32) value specifying the length of the following data. It can be ignored if you know the data size and have a buffer of the appropriate size (which is required to be pre-allocated before receiving the data in languages like C/C++/C#/etc, I don't this is required in Python). The actual data is exactly as in the telemetry map. |
Also, since this is a draft pull request, anyone should be able to commit although I don't really know how that works. |
Support for OS X builds
Is there any kind of "estimated date" for when this will drop? Thanks, JPL! |
Technically it's ready, you can already use it when you download the artifact on my fork or build it yourself (keep in mind that artifacts are currently x64 only). |
I had actually downloaded the src and built with CMake (Wins x64) and then built the Solution and it appears to be working, I didn't notice the artifact! I connected via a console and received data (albeit a bunch of scrambled chars/symbols)... i will hook up a JS script later and get some bytes! |
Actually it's supposed to be what you received, these bytes are actually exactly what was used before, with addition of an Int32 (4 bytes) at the beggining, which indicate the size of the following payload. Current implementations that receive and parse the data can be adapted by basically receiving the data from a TCP socket instead of a Memory Mapped File and skipping the first 4 bytes when receiving the data. EDIT: Unlike ETCARS which sends the data in a JSON format, this plugin basically sends the memory that's assigned to the telemetry map type |
I finally managed to look at the changes in more detail. I'm sorry for delaying this pr so long, but it's a big change, so I need a bit of time which I did not manage to put into this project lately. Beside some smaller support, this big change was sadly too much. Thanks for that much afford. Also fixing old mistakes and formatting mistakes. Most parts look good. Here and there I will change code formatting, but that's more or less personal preferences. I will check for a linting GitHub action in the future. I currently prefer the current event handling implemented with rev 11, but that was later introduced than the start of this pr. ... Maybe neither the new nor the old way will stay, when subscriber pattern is used? At least, I think it would be possible to broadcast the data direct at the gameplay event. Then it would be an event by itself and no extra flag/switch/state/... needed. But that's just an idea at the moment. Some minor things I need to test, because I may have some questions on them. There are also some small changes I may do. Possibly I can get rid of some commentaries and old to-dos before creating the new dev state out of it. Beside the other points, I think
is one of the important to fix, before merging. For memory leaks, it will probably code check up and observing application memory while doing a longer test. Perhaps I find some tool that can help here. Additional to fixing mentioned things, I'm currently thinking if it is useful to add the subscriber pattern in this pr or later with an additional pr same with string and trailer optimizations. |
ETS2-TCP-Telemetry-Byte-Map.xlsx This is a Excel document I made to quickly reference where each Value can be found. It's here for anybody to use if they wish too! You'll notice "End Byte" has 2 columns, this is because some languages want the byte after the range you want (non-inclusive), whereas others are happy with inclusive ranges! Enjoy, |
I felt free to directly pushed into your branch, I hope that's fine for you. Most/all are format changes or changes on comments. And remove the logic from events bits, like in the current main branch. I tested it a bit with the above python script and displayed in game speed. Seems to still work after my changes. Also, logging seems to work wonderful. The Excel sheet was already helpful for that. Thanks JPL. May I should include a Markdown table with that information. Performance seems to be ok/good already (windows 10). However, I'm exited to work on the optimizations for strings, trailer and the pattern. -- I will check this on Linux and go another time through the code if I overlooked something. If I have then no questions/changes, and you have no changes, I would like to merge it and work than one the next steps |
I would like to suggest a few additional changes:
Further ideas:
In spite of all the above, I've tested it working in OSX (and even on an Apple Mac M1) -- it works, works great. |
That's a great idea, I've thought about that but never got around to implement it
I'm aware of this issue, it's just hard to do any asynchronous socket communications on any system, especially in C/C++. I haven't encountered this issue on Windows and Linux (with accepting), but I've encountered a problem with the game hanging when the client does not receive data and fills the buffer. EDIT: I don't have any way of running ETS2/ATS on a MacOS system (unless you have some way to run MacOS in a virtual machine, DM me then), so any help with MacOS sockets is very appreciated. |
@alphavector I have sort of worked around the game stutters because of the connection system by using socket.pause() // socket.resume() whilst I'm parsing the last buffer stream. Edit: Disclaimer, I've not focused on events yet, but everything else works as normal! Truck/Game/Job etc |
The ideas are great. Will come on the list. Some of them are already on that list. The functions will be added when this pr is in dev. At least that is my current plan. That there is still some blocking is not so great. I also can not test OSX. However, I found this code int srv = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int flags = fcntl(srv, F_GETFL);
fcntl(srv, F_SETFL, flags | O_NONBLOCK); // setting the socket nonblocking This sets the non-blocking with another syscall. Maybe this is possible? Could you try this out? Tested Code for Windows and non-blocking... added a sleep in python and non-blocking, but totally behind the live values for sleeps bigger than maybe 100ms or so. For 1 sec, the data doesn't seem to update at all. I'm not sure if I did here every thing correct. Need to check that. set the socket to non-blocking u_long iMode = 1;
int iResult = ioctlsocket(srv, FIONBIO, &iMode);
if (iResult != NO_ERROR) {
printf("ioctlsocket failed with error: %ld\n", iResult);
} and the error Just for curiosity, how big was the zeroQ implementation at the end? I need to know how much salt this non-blocking and subscribing will create, because I said to not use an external library. |
@RenCloud, thanks for the idea, I'll try it on the mac. Sorry for being away for a while. :D I had the idea to try to implement a GRPC server, so far I managed to convert the telemetry structure into a proto file and write an asynchronous grpc server. In the near future I plan to finish it. And we will be able to evaluate all advantages and disadvantages of tcp/zeromq/grpc and choose the best way, if nobody minds. Regarding the implementation of the possibility to specify the user port: there are problems here, if we specify the environment variable in the terminal, it is available only during the session (while the terminal is open). If you specify in ~/.bashrc ~/.zshrc, then again, this variable is only available for the terminal, the game does not see it. I think it would work if you run the game through the terminal, something like
|
@alphavector I use the Terminal for a lot of things but running games isn't one of them 🤣 --EDIT-- JPL |
That's what I meant, it was a rhetorical question :) 99% don't run games through the terminal |
We can do this. I'm just a little dissatisfied that ndelta0 first created a version with zeromq, then at my request another one without library and now maybe it will be one with library 😅. But when the end result is better for the user and makes the development so much simpler, I guess I have no real argue against using one header file... 😄 |
Hi, I'm also interested in Protocol Buffers format. Even without GRPC and using the current memory mapped file it would help a lot. Since protobuf parsers are already written in many language and are production ready codes. @alphavector any chance to open source your |
I promise to finish it soon |
Thank you for answering and sharing the proto files, it would help me quite a lot. Also there's no need for promises, it's an open sourced project and you should finish it at your own pace. |
Hi, just curious if there has been any progress on this PR since the last comment. I am writing an application based on Electron however versions of electron higher than 20.3.8 have issues with memory mapped files being loaded due to some security changes, so I am stuck using an older version of Electron. If this PR is almost ready to use id be happy to trial it for a few weeks across my application as a development rollout and report back any difficulties I have in getting it set up? Massive appreciation for you all who have worked on this PR so far, it is a life saver for people trying to use this with JS/TS projects, and anyone trying to integrate this project into a CI/CD pipeline. |
@AltriusRS as You said it, the PR is basically ready, with exception of few quirks and minro bugs. One big downside is that it's for SDK version 1.17 (ETS2: 1.44, ATS: 1.44), but it will work (just won't have the new available data). Since it's nor merged into the main repo, you need to compile it yourself and redistribute it. If you need, I can provide you with help on how to do that. In that case contact me through any means listed here: https://k4rasudev.me/contact. |
sounds good, Ill be busy for a couple more weeks with my current work, but I shall get back to you once I have gotten it working to report my findings and difficulties. |
Hi there, I'm currently working on a StreamDeck plugin which get telemetry data from your plugin and change display of icons keys according to parsed data. The main limitation is about reading SharedMeMoryFile which is not possible as Streamdeck plugin is running within a closed process environment AFAIK. BTW, I succeed to wrap data from SHM and expose it with a custom python REST server. So the addition of network streaming stack could be really great. Some remarks :
Anyway you all made a great job and would like to thank you for that and your effforts. |
This version uses no external libraries. It's implemented with TCP sockets for each of the OSes (Windows and Unix). The server listens on
0.0.0.0:45454
. The transmission format is as follows:On my computer (i7-4790k) there were no perfomance drops in the game with the telemetry being sent every simulation frame. From what I saw in IO Ninja, the bandwidth that it requires is applicable only for local network data transfer and fast networks (I think it was about 1.5-2 MB/s).
Known Issues:
Compatibility:
The project is set to build on Linux x64, Windows x64 and Windows x86. I only tested Windows x64 and Windows x86. It's not confirmed nor said to work on MacOS, but it's possible to work with minor or no tweaks.