I don't care how many angels can dance on the head of a pin! What I want to know is how many tiny details can one devil simultaneously be in.
The only reason why my love for graphical user interfaces (GUI) suffered no loss over this past week or so is that I hadn't any such love to start with. The clientside required bits and parts for performing actions turned out to be a considerable pile of small but quite detailed pieces that seem tiny each on its own but add up quickly to eat a lot of time while remaining otherwise hidden internals so that there is at first nothing to actually show for all the work. As I looked in more detail at what the GUI needed to be able again to fully interact with the world, the work seemed at first to just keep growing at every step instead of shrinking: there were GUI elements missing and then new methods required for querying the local cache and new configuration options and synchronizing and whatnot.
Experience helped here a lot, as I know this sort of pile-of-details stage for exactly what it is, part and parcel of work at times. So I just kept the work as contained as possible and otherwise I kept going with it until I finally brought it all to the point where there are enough of the required internal mechanisms in place so that they can support the desired GUI interaction itself. As a result, I can illustrate now at least some of the new additions, if still not all. At any rate, Eulora's client has now in place the basic mechanisms for interacting via mouse or console (text) with any items or characters in the world, whether they are contained in one another or simply directly in the world, on their own. There are still all sorts of details that will have to be sorted out - or possibly altered even - as everything else comes together but those are secondary details, those that can never be fixed in stone at the first pass anyway, nor should they ever be so inflexible as to have to be fixed in the first place.
To start with, the Console has increased usefulness and usability. The most important improvement from my point of view is that there is now in place a generic mechanism to deal with any command from the user: the first word is the command itself, while any following text is read as a list of "parameter=value" tuples, where the order does *not* matter and there is no restriction whatsoever on what "parameter" might be. Basically the Console simply grabs the full text, uses the first word to find the action that goes by that name (if any) and then passes whatever text follows to the action itself to handle. The action in turn has its own default values for all parameters but then goes through the given text and sets the given values as found, if and when found. As an interesting effect of this approach, the user can even set the same parameter several times in a single command but the value used will simply be the last one encountered. Moreover, as much as possible the same letter stands for the same thing for *all* actions - the most obvious example is the target which is t everywhere, not like it's all that difficult, really. Anyway, by means of illustration, here are two screenshots with some commands:
The above new wiring of commands to actions means also that I can now easily add new actions at any time, since it's just a matter of implementing what the action is meant to do and otherwise adding it to the list, nothing more - all the wiring from Console and even from the rest of the GUI will simply adjust and include it too, as it should. In addition to this, there are a few more small but rather very useful improvements including clearer feedback from entered commands, resizing of the Console window so that it correctly resizes the two internal parts as well and a 1-line "history" so that one can recall the previous command at any time. In funny inherited weirdness that I'll probably have to look at later on, it turns out that a resize has as side effect the reset of the font's colour though! Such is the underlying nature of the inherited core widgets, this ever plentiful source of surprises of the most... surprising kind.
As you can perhaps notice in the illustration above, the GUI offers now the full list of actions defined in the communications protocol but also a few additional "actions" of its own, such as "pos" or "examine". The reason for those additional actions is that they are simply quite convenient for the user and entirely a clientside concern: one might want to find out their exact position for instance and the GUI can expose that easily so I'd very much rather it did. There is of course no limit to what can be added there either but I didn't spend time to polish this: the point for now was to have the very basics in and otherwise have it there as an example rather than anything else. For illustration, here's the result of "examine" applied to the character itself:
While the Console remains to my eye the easier interaction option the user can have, I've nevertheless put in the work required to have a working mouse-powered option as well. So the skin.zip file got bigger and includes now at least one icon for each type of (inter)action known to the client. (And don't ask me why is the "repair" icon showing a hammer crossed over by a rolling pin, I can't begin to imagine where that combination comes from!) Those icons are then used in a new Context window that can be accessed with a right click on any item1 and provides links to all the known actions. And since my GUI is not made with love2 but with calculations whenever possible, this Context window simply uses basic trigonometry to just figure out where each icon goes so that all actions are shown neatly in a circle. As a consequence, if a new action is added, the Context window will simply adapt and include that too, there's no need to add it manually and fiddle with its position through xml until the cows come home. Such are the results of bringing the ancient magic of the sine and cosine to the innocent lands of GUI and other computer ruralia! Lo and behold the euloran outer wheel of perfect roundness and plentiful context interaction (see the console in there for feedback on clicked actions):
Getting back to the actions itself, with the exception of lock and exchange, all the other protocol-defined actions are currently fully wired into the client, meaning that the relevant messages are created and sent to the server. The movement action is at the moment rather annoying and choppy so there is certainly more work needed there but I think it should still wait as some of the issues are likely to get smoothed out anyway as everything else advances (part of the choppiness is likely to be more a matter of the values I have currently set for the sync intervals for the whole world, for instance). Although I didn't fully go into all the remaining movement part at this time, I start thinking that I'll have to do that too at some point, most probably to finally kill that stupid of "leg length" and "falling below 0", if nothing else. Nevertheless, it can still wait a bit, perhaps.
Arguably the most time-consuming "action" in all the above was the move/pickup since it required the whole inventory GUI with slots and equipped vs non-equipped and stacks and splitting stacks and moving items in inventory too and everything under the sun in there. There was a bit of mini-puzzle fun with the formula for inventory (non-equipped) slots, some annoying further misbehaving of that listbox that has the handy scrollbars and all sorts of weird discoveries regarding the number-prompt window. Nevertheless, the whole thing is now working, the Contents window got basically an upgrade, can move items about and is quite ready to be of further use as half of an exchange of any sort. The "move" action on items in the world is effectively a "pickup" - it will attempt to move the items to the next empty slot (calculated on the fly, too) in inventory and won't care a bit whether that is possible or not possible. After all, you never know unless you try so my GUI here is not at all in the business of telling the user what they can and can't do: it provides the widest set of options to everything and then dutifully executes what the user asked for. The inventory window updates with server-given data only on reopen (all it takes is to press i for that) but otherwise it will happily show the user whatever they thought they could do, pretty much. I'm quite sure that there are all sorts of details to change here on future iterations but for this first pass, I think it does as much as can be done for now:
For the number input window, I initially wanted to reuse the original window as it was since it had in place some input checks and limits and all those things that are in principle quite useful. The fun part started though when it turned out that it had of course all sorts of silly expectations - that got therefore cut away - and otherwise it used a horizontal scrollbar to allow the setting of the amount via mouse movement. This horizontal scrollbar was simply not able to use 64-bits integers without requiring otherwise a full update throughout the whole client, basically in all places where a scrollbar is used at all. So rather than indulge in such waste of time, I just dropped the silly scrollbar-set from this window and otherwise updated the remaining small part to deal with 64-bits integers, what else. Since I was at it, I added also overflow guards, as there were none but other than thatm the thing is (at least now) small enough to be perhaps of some use currently.
On a side note related to inventory and slots in general, I added again the quantity and quality labels to each slot but the trouble is that the maximum 64-bits value has 20 characters and to fit as many as that onto a slot, the font ends up so tiny as to be unreadable. So for the time being I let them be as you can see in the screenshots above, using a reasonably small font that means however that the full value might simply not be visible at times. I suppose this might remain as one of those low-hanging fruit to pick for any client developer out there.
Regarding the actions themselves, on serverside, at the moment, those action messages that the client sends are received, unpacked, recognised as what they are and otherwise promptly discarded. There's quite a lot to implement on serverside before they can fully be acted upon as intended. Nevertheless, for current testing and illustration purposes, the serverside simply has some mock data that it sends to the client as "the world" and that is quite enough for the moment (though it won't be for much longer, by the looks of it all).
With all the above in place and working, there would still be the exchange and lock actions and corresponding GUI elements as such. Other than that, there are various non-GUI parts that could be done (and need done at some point anyway) on the client, such as the management of Serpent keys and actually dealing with a change of connection/server on the fly.
Let me know in any case if there's anything else/different you want done for the GUI part at this stage and otherwise if there's something else specifically burning/best to tackle next. I should also mention perhaps that in the interest of documentation and seriously applying myself to learning the craft of GUIs, I have indeed reinstalled Diablo as well and gave it a spin - the windows are a pleasure, the tick-tock of idiotic walking is more annoying than any skeletons that might appear from the barrels. Nevertheless and purely for work interests, I shall therefore endure Diablo re-plays whenever required!
This ran at first into a weird "attachment" thing that apparently was required in order to have a direct link between CS meshes and the game objects that the remaining client core works with more directly. And when that in place, there was the repeated and infuriating further run into the PS notion of "any item", such as it still remained in the various parts that are still in use in any capacity: "Oh, by any you surely *don't* mean meshes AND moving items, do you?" and "Even if moving items too, then *surely not* your own character, too!!" and so on and so forth, it's like the devil is not in the details but rather the devil is a detail inside a detail inside a detail inside... ↩
By now this made-with-love advertisement stands as far as I can tell for "it will blow up in your face but you should be happy about the blow up, because it didn't mean to do you any harm!!". Here's an illustration, too, some typical result of the made with love approach. ↩
Comments feed: RSS 2.0
Experience did indeed help a lot, didn't it ; and discussions and workings on and towards the republican irc, and...
Neat!
> a 1-line "history" so that one can recall the previous command at any time
What's wrong with lifetime history, saved by the client in a specific file, such that the player can recall any command ~ever~ entered as well as prune it howsoever he pleases ?
> it turns out that a resize has as side effect the reset of the font's colour though
Well, resizing requires a repaint, so that's probably where it's from.
> There is of course no limit to what can be added there either but I didn't spend time to polish this
Actually, I'd say your diligent and (more importantly) productive work has by now piled up on itself to the degree significant narrowing down of the ooda loop would probably immensely benefit. So, how do I go about running a client of my own (I don't mind following along doing nightly rebuilds or whatever you do), and... shall we re-activate irc, or what do we do ?
> and is quite ready to be of further use as half of an exchange of any sort
Yes! That's precisely what I was expecting to read, in due time.
> only on reopen
That's the right way to do this.
> I just dropped the silly scrollbar-set from this window
I don't know that anyone (sane) ever used that scrollbar for anything, so good riddance.
> By now this made-with-love advertisement stands as far as I can tell for "it will blow up in your face but you should be happy about the blow up, because it didn't mean to do you any harm!!"
Well... like ejaculation works, right ? Careful so you don't get the love in the eye.
> value has 20 characters and to fit as many as that onto a slot, the font ends up so tiny as to be unreadable
No, no, recall the spec ? 1-999 ; 1.55k 15.5k 555k ; 1.55m 15.5m 555m, 1.66e66
I very much like the different colors, tho!
> otherwise if there's something else specifically burning/best to tackle next
I've been going through endless iterations of the combat model, which I'll dump on you in the coming weeks ; but until then the paragraph above describing things still in need of being done is perfectly to my heart's own content.
> I shall therefore endure Diablo re-plays whenever required!
Win.
Nothing other than it doesn't yet exist! The 1-line history was meant mainly as the cheapest possible in-console recall ie to not have to retype a command just because of a mistake or something. If the not-cheapest is considered worth it though, I'll add it then to the todo list, it shouldn't be a huge thing anyway (though yeah, one of those adding up but at least it adds up a lot of usefulness too, it is true).
And what, the repaint ran out of green colour, you think? Sure, a repaint but wouldn't any sane person expect that the repaint uses the ...paint colour? Well, not that is all that surprising news that the widgets stuff is not entirely sane but apparently my capacity for being surprised is endless.
Yay, I'll take a bit more time then to pack it and write a script for the whole build-cs-cal3d-set-this-that-build-run thing, since I really think this will be needed for the release anyway, so the sooner done the better (it gets some testing itself, too). Currently I keep it all local and otherwise V-versioned so it's basically simply a new vpatch whenever I add some working part. I can easily set this up so it mirrors the v-tree on the server whenever there is something new but it's anyway really low-key ie at most get a new vpatch, press and rebuild, that's all. It's the initial setup only that is potentially a bigger pain.
At the moment the test server is local as well. While the client can happily run entirely offline, if you want to test/see the communication parts too, I'll deploy the test server too.
For live communication I still don't know of anything other than irc that would work best.
Ah, good that you reminded me, for some reason I had entirely forgotten about this. I'll work it back in, certainly.
Great to hear it!
g++ psengine.o -L/usr/lib64 -L/usr/lib -lz -lpthread -ldl -L/media/lordmircea/d7c35c5a-433e-4702-ad32-a55d556d0e49/lordmpoftmsr/eulora2/gpr_cal3d/lib -lcal3d -L/media/lordmircea/d7c35c5a-433e-4702-ad32-a55d556d0e49/lordmpoftmsr/eulora2/cs -lcrystalspace-2.1 -L/media/lordmircea/d7c35c5a-433e-4702-ad32-a55d556d0e49/lordmpoftmsr/eulora2/eucore/lib -leucore -o euclient
libclient.a(pscelclient.o): In function `GEMClientActor::SetAnimation(char const*, int)':
pscelclient.cpp:(.text+0x25ed): undefined reference to `CalModel::getCoreModel()'
pscelclient.cpp:(.text+0x2619): undefined reference to `CalModel::getCoreModel()'
pscelclient.cpp:(.text+0x2698): undefined reference to `CalModel::getMixer()'
collect2: error: ld returned 1 exit status
gprbuild: link of psengine.cpp failed
FAILED building GUI/Client - are CRYSTAL, CAL3D and LD_LIBRARY_PATH environment variables set correctly?
1. LD_LIBRARY_PATH should include the eucore/lib directory as otherwise eucore lib will NOT be found.
2. CRYSTAL environment variable should point to the CrystalSpace directory on your machine.
3. CAL3D environment variable should point to the Cal3D directory on your machine.
4. LD_LIBRARY_PATH should include the libs directory of Cal3d (cal3d/src/cal3d/.libs) unless you install cal3d globally.
I reproduced the trouble and figured out what's going on at the root cause there: apparently ld on ubuntu > 12 gathers symbols from linked libraries in a ...different order than the rest/before 12 so that although the library is linked fine, it still goes "unrecognized symbol" as it ...didn't know it needed it so it didn't include it. For the good news, it seems I have also a working solution for it - I'll test it a couple of times/on various environments and then update the client's tar.gz (as the rest should be fine as it is).