There's still quite some work to do before having a fully working client as well, but I can happily report that the most important part for that auto-updating version of the client is indeed in place and working: an initial prototype client 2.0 can now start happily with nothing at all (no keys, no graphics, no knowledge of the world at large) and then generate keys, obtain an account, retrieve (and check) sector and model files, load them when it got them, even let the resulting euloran move about and admire its reflection in the wonderful water by the rocks:
For future reference and current unloading of a fresh set of troubles sorted, here's the list of main updates done on the clientside:
- EuCore (data acquisition logic, Ada):
- Setting RNG source via config file: whatever string the user provides in there (e.g. "/dev/urandom" or "/dev/ttyUSB0" or "/silly/ass") will be used as source of "random bits"; NB: the indicated source, whatever it might be, is considered already initialised in whatever manner is required, since it makes no sense at all to try and initialize from EuCore's code a source that can be set to anything at all. For all the apparent "easy" label on this additional knob, there was a significant headache to make it right, since the RNG source is used from both C/CPP code and Ada code so that it has to be set across language-borders, not to mention in the precise direction previously-avoided-to-keep-things-neat-and-less-confusing. Not that I can recall *any* time when I got to keep over long term any of those parts that were easier, it's just not my thing or something. What can I say - it's done now and it's working (the default is urandom).
- Setting a "sync" interval - meaning how often the user wants EuCore to attempt to resync its local data with the server. This is important mainly as a means for the user to find the compromise they want between generating traffic (which has a cost) and otherwise keeping their local data cache up to date (since out of date information can presumably make play rather less than ideal). Worth noting here that this "sync" interval is important for movement update and for requesting World Bulletins regardless of other triggers that might apply.
- Creating account and obtaining BOTH sets of Serpent keys from the server - this got a refactoring and update to reflect the clear separation between EuCore that does *all* data logic, acquisition, storage and so on (hence it's the only part that can request creation of RSA keys for a new account for instance) and what is simply a dumb GUI - the former "client" that will focus exclusively on using and presenting data that is present, nothing more. There was also still pending - due to previous lack of clarity at least in my understanding of this part - the issue regarding the initial set of Serpent keys for communication with the client. While the protocol allows for the client to generate those and send them to the server, at the moment the client will simply keep sending request for an account until it receives those too. Perhaps at a later stage I'll get back to this and implement also the option + knob to generate them locally and send them to the server but this can certainly still wait.
- Updated EuCache (the actual data storage structure that provides thread-safe access) to reflect the latest, streamlined data model.
- Updated the data acquisition logic to actually send requests to the server for each and any bit of missing data (be it object or file) as soon as it becomes aware it's missing. This includes proper packing of file requests in as few messages as needed (instead of firing up the wasteful one message for each request).
- Updated handling of objects to fully update local data cache correctly (in short: adding those in server's view and not in client's view, deleting those in client's view but not in server's view, asking for anything missing and fully walking the structure at regular intervals, to ensure re-sync).
- Updated handling of file received messages so that chunks are saved as received and the Keccak hash of the file is calculated + checked against expected value at the end, deciding on whether the resulting file is kept and made available to the GUI or otherwise deleted (+ new request sent to the server, to resend it). NB: the approach here is very basic for now in that chunks are literally saved in the order received and therefore it's enough to have 1 message lost or out of order to result in an incorrect file and therefore repeat the request. I'm sure that this can be made better - not so sure though that it's worth the trouble to sink time to make it better *right now* and so there it is, low hanging fruit for anyone who wants to improve their client.
- Updated interface towards the GUI to reflect the new understanding that the actual needs of the GUI are way, way simpler than the full complexity that the protocol and more generally the world structure allows (and here's an example of where the doing-it-all kind of made me stumble because even when it's the "same thing", it's from different perspectives, of course and so I need to keep them all in mind at the same time and change swiftly between them, oh joy). At any rate, now the interface provides the sort of packing that the GUI finds useful, while taking otherwise advantage of EuCache's data structures that reflect the actual hierarchy of the world. That's pretty much the part that wasn't quite that obvious for me until now - the dumb GUI is in fact way, way flatter than the actual world as it were and as such, there's really no point to make the GUI more intelligent than it can handle. Let the GUI be an idiot that is forever concerned only with "what can I see *right now*" and that's that, everything all of a sudden starts to fit, too.
-
GUI (the former "client", cpp) side:
- Refactored the SMGData interface to work with the latest EuCore interface and provide a single point of access to all data, from objects to files. Sorted out here some unexpected issues with importing constants from Ada into C as well.
- Nailed down a working model for this whole GUI stuff: there's a logic (such as it is) part that will then make use of all the paste that used to be pompously "the client", from pscelclient to psmovementmanager and whatever. Sorting this out was a pain but the result is a very welcome insulation from the rapidly-spiralling-into-madness mess. In other words: while the mess is still there for it will take ages to fully eradicate, one doesn't have to work neck-high into it *at all times* anymore! At times, a descent into that is still needed but I'm finally at the stage where it's "at times" as opposed to "all the time".
- Updated and refactored loader actually capable of making full use of .zip files that were acquired *after* client startup! This was such a pain to get working, as the virtual file system thing is rather poorly documented and quite clunky at times. Nevertheless, it ... works!
- Prototype implementation of "soft reset" - essentially the PS code insisted that one needs to go through 1001 things in 10001 places to just clean up if/when the sector changes for instance but then it turned out that CS has this nice and shiny red button to ...DeleteAll! And once that is done, PS can go and get stuffed since there's not much it can do anyway. So the prototype so far aims to simply do such a soft reset if something crucial like the sector or the player themselves suddenly change - it would seem possible that we don't actually have to end up with the sort of Windows-style-restart-the-client, after all.
Aside from the above, there are many other smaller details and issues sorted as they appeared - some of them might even further change as everything takes further shape. So far though I'm satisfied that the former client-code is finally just about paste-enough to be of some actual use instead of unrelenting pain and misery.
The next steps are for now to iron out some remaining weirds in the current minimal prototype and to further develop the actual use of data from the GUI since for now there's really only the sector+player check, retrieval and loading of corresponding graphics assets but nothing further connected. Local movement works, of course, but it's all local and moreover, the GUI doesn't yet request from EuCore anything *other* than the player itself and the sector where they happen to be.
On the write-up front, there's the structure of the .zip files for sector + cal3d models to write and publish. All is quite clear and neat there but I need to find some time for it and I might possibly do first the loading of CS meshes too.
On the iffiest client-side part remaining, the paws widgeting mess looms largest. At the moment I can't tell if or to what extent I can sidestep it/any of it but I'm certainly not keen at all to get into that swamp even an inch more than is absolutely and unavoidably required.
Comments feed: RSS 2.0
Pretty cool! My excitement is definitely ramping up!
Some odds and ends :
I think I want a much more flexible equipping model than anything games (ever since at least Artifact's Demise twenty years ago) ever seem to offer -- specifically there's no good reason a hero can't equip ten rings or more, and as many bracelets and amulets as she can lift off the ground. Evidently the limit must be something else other than count, and consequently the dolly pre-set count-based limit made possible will have to be retired. Upon consideration, this venerable commonplace of computer games seems rather retarded windows-guiolade, an intellectual dead-end that fruited beautifully in say Diablo but at a great cost that went I suppose mostly unperceived. In any case I'm retiring it, meaning you can chop the whole equipping dolly in Eulora ; we'll handle equipped state otherwise (prolly via description text, I guess).
I don't think it can ship without, actually.
Agreed.
Word!
You're making blazing progress, it's a pleasure to watch.
It certainly seems exactly that. The *only* visible reason for the whole fixed set of x rings and y things is that the... graphics part had to know upfront what and where and what sort. Exactly the sort of killjoy that ended up so popular as to nearly kill the field entirely, or possibly sterilize the field entirely is better said.
Gladly! Off with its... dolly! Btw, atm we don't actually have working "sockets" (to plug supposedly one model into another) - those apparently need to be defined yet again at vertex level, making them a very dubious approach in the first place. Not quite sure what/if I should aim to figure out some sort of solution for this anyway.
Ok. It will have to be done then, some time before the client ships.
From within, it seems I tend to lose perspective at times, so it's very helpful indeed to hear this, thank you.
Incidentally -- by design the game world is supposed to be ultimately clusterizable, such that in principle each sector could be handled by its own physical machine. I've no intention to do this for the short to mid-term, but on an as-needed basis the world can be split, both geographically (such that say the endless plane of sectors is quartered diagonally and there's a server each for N, E, S, W) and specially (such that certain sectors have their own server, principally sectors that are well developed / popular cities). The only point where this is of interest to you now is that somewhere in the world bulletins the server should say what server (ip) is responsible for so and so sector, such that when the client traverses a sector boundry it repopulates its server address (and in principle all servers should passive gns, in the sense that if a client who's located in a sector they're not responsible for attempts to connect, their response should include a reference to the correct server).
Makes perfect sense and it's indeed very useful to know now. I'll have to see how to enable the client to use this, preferably without restart.
[...] of Software book" and you'll find it all there. ↩I'm talking from direct experience with fully taming such a chaotic beast, not that I ever actually wanted to gain this sort of experience nor [...]