This menu, known as the minimenu, is a very critical input mechanism that drives almost all mouse/touch input across the game. Every single frame, the game works out what is underneath your pointer and builds the list of options for you to pick from - even if the menu isn't open! The order of this list is very important, as when you left-click (or tap), the game actually just selects the top entry in the menu for you. However, this order is quite complicated, as it depends on many factors:
- •Distance from object to camera
- •The order entries are defined per-object
- •The value of items on the ground
- •Whether the object is your PvP target
- •NPC and Player attack options
- •Follower NPCs are deprioritised based on a setting
- •Players with the same team cape are deprioritised (did you know?)
- •...and the list goes on!
We're going to get a bit technical now! In the 2007 code, this order was fairly simple to achieve: things would be added to the menu already in the right order by default, excepting a few entries that would be shifted down to the bottom. This order was actually tightly-coupled to the 3D renderer; the 3D renderer drew every object to the screen from back-to-front, and would record everything under the mouse as it did. This then incidentally leaves you with a list of objects under the mouse, in reverse order. Flip that list, and that's the order that the objects should appear in the menu! Unfortunately, as we expanded the functionality of the menu in the official client, things got more and more complicated. This incidental order was no longer fit for purpose, as now some things needed to shift to the top, some things needed to shift around 'walk-here', some entries needed to appear only when holding shift, and we even decided to allow full reordering, rather than just setting a single left-click entry per object. On top of this, since we switched over to Z-buffered rendering, the 3D renderer no longer draws objects in the nice, neat order that it did before. Simply put, the original structure of the code was no longer suitable for everything we wanted to do, and some big cracks were showing. Rather than continuing to try and paper over these cracks, we needed to carve out some time to properly rework things. There were a few programming principals that we needed to get back to:
- •Decoupling: Any system that wants to add an entry to the menu should not be concerned about where in-sequence it is attempting to do so. The order of the menu should not be incidental, it should be well-defined in a single place.
- •Single source-of-truth: The code that detects when your mouse is over an entry, and the code that draws the entry, should not both be independently working out the size and shape of that entry.
- •Single-responsibility: It's hard to know where to look when all the code is in one big class named "Minimenu". Separate the data from the view, and split it up into individual components that only know what they need to.
There's a lot more tiny details we could go into with a system as fundamental as this menu. For example, the way that tapping something will invoke the action on release, while left-clicking will invoke an action on press, unless that thing can be dragged, and if you start dragging it but then switch tabs with an F-key we might invoke it anyway, yadda yadda. Suffice to say, it was not a simple task to rework it all whilst keeping it looking, feeling, and functioning identically to how it did before! The end result, though, is that this should now be a more reliable and more flexible component of the game, that we will be able to do more with, more easily, from here on. We can add support for different styles, larger fonts, better internal debug features, and some other nice things like the new menu entry swapper! So there you have it, that's everything you need to know about our Menu Entry Swapper overhaul! Remember that it may take a little time for the update to roll out to your device, and to keep an eye out on the app store in case you need to manually update. We want to know what you think! We'll be closely monitoring your feedback, so make sure to leave your thoughts and any bug reports in the #mobile-bugs channel in our Official Discord server.