As Delaford is very much a point-and-click game, understanding the Context Menu is very important for development.
That being said, we know the current code at server/core/context-menu.js
can be enhanced. There are many opportunities for abstraction and low-hanging fruit, if you'd like to make a PR.
Upon the instantiation of the Context Menu
class, we take some parts of the global world
object, take the current player and its mouse coordiantes and some misc data and get to work.
The list of actions that can be performed by the player are located at server/core/data/action-list.js
. Most of the actions take some shape or form like this:
{
name: 'Mine',
actionId: 'player:resource:mining:rock',
context: ['gameMap'],
allow: ['foreground'],
nearby: 'edge',
weight: 1,
queueable: true,
}
The label of action that is displayed on the context-menu. For example, Mine Rocks
or Examine Jatite Sword
.
The unique ID that is used to identify and select the action between the socket and client handlers. It usually follows the notation of this:
Those, when put together, are separated using a :
character. For examples, here are some: player:resource:mining:rock
, player:left
, and player:context-menu:action
.
Where, on the UI, can this action take place? When you right-click on the UI, every element has a class selector. The most common one we'll use is gameMap
for the game canvas.
Some actions, like examine
, can have multiple contexts such as: ['gameMap', 'inventorySlot']
. Equip
and Unequip
, for example, have the context
of ['wearSlot']
.
The allow
value gives the context-menu the ability on where to check. Some actions will allow on multiple entities like examine
which has the allow
of ['npc', 'item']
. Some have an allow
of foreground
which only allows an action on (certain) foreground objects like player:resource:mining:rock
.
Actions can have multiple allow
values and usually always have more than one.
Every action needs precise location on where that action can and will take place. For example, sometimes an action can take place from anywhere. examine
is one such example. Other times, an action will need to be exactly on the spot like take
and other times, it has to be near it like Mine
and Push
.
If any action's nearby
is anything but false, they will be eligiable to be queued which means the player must reach there first before doing said action item.
Every action must be analyzed based on what kind of action it is. The more destructive actions like Drop
and Release
go near the bottom and thus have a higher weight
count.
The more use you think an action will have, the lower count it receives. examine
, for example, will always be somewhere in the middle but never at the top nor the bottom.
The cancel
action item is attached to every context-menu list generated no matter what to give the user a quick way out. It always at the end of every list.
walk-here
is always attached to every list generated on the gameMap
context. It's position determines on whether user has actions to perform on resources, items and other things. If that criteria is met, then the walk-here
is then placed 1 item below the main function. If not, then that action item is always at the top.
When an action is queueable, it means that that action can be chain with others. For example, Take
can be chained with walk-here
.
Queueables are most used for actions whose nearby
is edge
or take
. From there, the walk-here
action is executed while the Queue system waits for the walk-here
action to finish before starting the next item in the queue.
After we secure the mouse coordinates, where the user clicked on the map (23, 234) and where they clicked in the viewport (3, 5), we get to work building the context-menu.
We start by going through the list of actions and filtering it by the allow
of which they allow.
The check()
method then goes through the action's context
to see which to cycle through. Then, the conditionals are checked and added to the list if they are met.