Replies: 6 comments
-
What I'd really like to do to start is make a simple cli client. |
Beta Was this translation helpful? Give feedback.
-
One thing you might try is reducing the number of asteroids and NPC ships. This will greatly reduce the number of items being drawn. You can go to the demon screen and type in "set NPC_SHIP_COUNT=10" and "set ASTEROID_COUNT=5", and then "regenerate". Might get you a bit more performance (but probably not enough.) The protocol between snis_client and snis_server is (mostly) described in doc/snis_protocol.html and also snis_opcode_def.[ch]
What is not described there is the interaction between the lobby server ssgl_server and snis_client, snis_server, and also snis_multiverse. Probably the place to start to look to understand that is here: Presumably your custom client(s) would also be clients of ssgl_server in order to locate the IP addresses and ports of any snis_server instances you want to connect to. There are some examples of simple ssgl gameclient and gameserver in ssgl/ssgl_gameclient.c and ssgl_gameserver.c. There is also a program in ssgl called lsssgl that you can use to interrogate ssgl_server to see what it is advertising.
In the beginning, if you want to skip implementing all this ssgl related stuff, you can just use lsssgl to find the SNIS instances and manually put in the IP address and port. The initial handshake between snis_client and snis_server... is some pretty ugly code. I wrote it before I had any of the UI stuff working, and, well anyway, it's ugly, and made uglier by the warp gate stuff that allows snis_client to switch to a different snis_server upon hitting a warp gate while in possession of a warp gate ticket. The function to start looking at in snis_client is connect_to_gameserver(). A thread is created to make the connection, there's a bunch of network code to resolve names and establish the connection, then it writes SNIS_PROTOCOL_VERSION down the socket (as defined in snis.h, currently "SNIS053", this 053 increments every time something in the protocol changes.) if the protocol doesn't match what snis_server was compiled with, then snis_server will disconnect. Then the client writes and OPCODE_PLAYER_UPDATE with various parameters down the socket (struct add_player_packet). This packet is "manually" constructed, unlike most other packets in the game. Probably because it predates snis_marshal.[ch] Then a reader and writer thread are started to read and write to snis_server. Then, snis_client_cross_check_opcodes() is called. Both snis_server and snis_client have a list of "formats" for (almost) all the opcodes, and snis_client transmits this list of opcode formats to snis_server (using OPCODE_CHECK_OPCODE_FORMAT, subcode OPCODE_CHECK_OPCODE_VERIFY). snis_server gets these and (see snis_server.c:process_check_opcode_format()) and for each opcode and format, snis_server verifies that they match (or don't) and transmits back to snis_client OPCODE_CHECK_OPCODE_FORMAT, subcode OPCODE_CHECK_OPCODE_MATCH (good) or OPCODE_CHECK_OPCODE_MISMATCH (bad). On getting and opcode mismatch, snis_client just prints a message and continues. (A protocol error will likely happen at some later point, or not, depending on how often the particular mismatched opcode is used. Some very obscure opcodes may be rarely used, so might not happen.) Anyway... all of that mess is there so that when you do screw up the protocol somehow, you figure it out right away. To build opcodes, look in snis_opcode_def.h at e.g. snis_opcode_pkt() and snis_opcode_subcode_pkt. This uses those stored opcode formats to verify that you use the right format, and if you don't, it prints out a stacktrace. It works kind of like printf, the format is described in snis_marshal.c, above packed_buffer_append().
So, for example, in snis_client, you might see:
so snis_opcode_pkt builds a packet consisting of 2 u8's and a u32 ("bbw"), with the values OPCODE_SCI_SELECT_TARGET, selection_type, and id. queue_to_server dumps this packet onto the front of a queue. On the back of that queue, the gameserver writer thread is chewing away, transmitting whatever's in there to snis_server. And snis_client of course contains a gameserver reader thread, which is receiving and interpreting opcodes transmitted from snis_server. Well, hmmm... that ought to be enough to get you started, or scare you away, or prompt some further questions. Good luck... you'll need it! |
Beta Was this translation helpful? Give feedback.
-
The easier way to do this is with Raspberry Pi 4's and arduinos and build up the snis-device-io stuff, like this project: https://spacenerdsinspace.com/snis-consoles/notes.html But I think I already told you about that, and far be it from me to discourage you in your project. |
Beta Was this translation helpful? Give feedback.
-
Thanks! I did think about using an Arduino but I just don't want to use an extra board haha. I'll try and keep you update with my progress. That is if I make any! |
Beta Was this translation helpful? Give feedback.
-
So I've been having a look through and I've been thinking it may be easier to just replace the ui then trying to pull out all the networking stuff. My thinking is I will try and pull out all UI stuff into a separate file first. |
Beta Was this translation helpful? Give feedback.
-
I think any way you slice it, it's a big job. Pulling out the UI.... I dread to think of what it would require. snis_client (and snis_server) were designed (if that is the right word, maybe "incrementally and organically grew" is better) as fairly monolithic programs. There are lots and lots of static globals... Maybe a first step would be to package up all these globals into a "struct client_state" or something like that, which you could then pass a pointer to this around, so that your UI module doesn't need to have a zillion "extern blah", and all those static globals don't need to be exposed as an API individually, I don't know. It's a rather huge job any way you slice it, I think, and more than a little bit scary. Edit: Please don't send me a gigantic patch that does a million things though. Also, I highly recommend stgit as an indispensable aid in creating a sane patch series for large changes. https://stacked-git.github.io/ -- steve |
Beta Was this translation helpful? Give feedback.
-
Hi again,
I've been looking into making a smaller client either to run on my low end devices or to run on embedded systems with various switches and knobs and stuff.
My idea is that the protocol could be split off as it's own library and then me or whoever else could just wrap it up and do whatever.. I haven't put much thought into this yet.
Do you think it is much work?
I've been looking through the snis_packet.h and snis_client.c and can't see any definition for what each client should be sending/receiving is this documented somewhere?
When I have some free time I'll take a bash at it and see if I can whip something up.
Beta Was this translation helpful? Give feedback.
All reactions