In Euloran Moving Updates: Inner Slots and Outer Wheels

August 31st, 2020

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:

gui_movement_2_640.png
gui_movement_10_640.png

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:

gui_movement_3_640.png

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):

gui_movement_4_640.png
gui_movement_5_640.png

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:

gui_movement_6_640.png
gui_movement_7_640.png
gui_movement_9_640.png
gui_movement_8_640.png

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!


  1. 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...  

  2. 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.