Class relations

(I suggest you open this diagram in a seperate window while reading...)

Relation types

This diagram illustrates the 3 different types of relations - normal, inheritance (extends), and container relations.  Extends means just normal Java class inheritance and Implements means implementing a Java Interface.  Container relations represent branches in the container tree (or container hierarchy).  The container tree is a bunch of connected nodes where each node has zero or one parent and any number of children (see the example).  Each node (ie Physical) has semaphores that show which events they are interested in.  When an event occurs, it will propagate to all objects are supposed to notice it, using the container tree as it's infrastructure.

Most relations are container relations, since this provides a nice consistent object structure.  In fact, the red container relations show how objects relate to each other while the black extends relations show how classes relate to each other.

And what about the lonely blue arrow saying that "World has 0-n accounts"?  That means that the world doesn't directly contain these accounts directly - it only keeps references to them.  Why?  Because the Account is actually kept as a child of the body which it controls (study the diagram...).  And an Account cannot have two parents, so I couldn't make it a child of the World as well.  In fact, if an Account is a child of the world it will really be a Soul controlling the world... kinda funky, eh?

Likewise, the blue arrow connecting Activity and Physical indicate that they are not connected via the container hierarchy (this would be impossible since Activity is not a subclass of Physical and can therefore not be in the container hierarchy at all).


Item is simply the top of the hierarchy, for items that have a name, an icon, and other such basic things.  Any classes representing objects that are not in the container hierarchy (for whatever reason) will extend Item instead of Physical.

Another important aspect of Item is that it has an abstract set of "properties" and can provide a "property viewer" that displays the values of these properties. Each subclass of Item can add it's own set of properties and expand the property viewer to display these as well. So, to summarize, all subclasses of Item:


Physical is the very heart of White Orb.  Almost everything in the game is a subclass of Physical.  A better name might be "Node", since it really only represents a node in the container tree. Not necessarily a "physical item" that can be seen and felt.  All event handling and container tree code is here.

The most important thing about Physical is the fact that it has a parent (or a location) and a set of children.  The only object that can have a null location is the World (the top of the container hierarchy).  Which means if you take any Physical and recursively check it's parents, you'll always end up in the world.

Physical also takes care of the event propagation so that events can travel up and down the container hiearchy, so if someone standing a few squares away makes a sound the event propagation mechanism will make sure the sound event reaches those that should hear it. But the details of that will be described in the event propagation document.


Some Physicals have Senses.  That means they can hear and see things.  Senses is a subclass of EventFilter which is just what it sounds like - an object who's sole purpose is to filter the events it receives.  Joe's Senses filter away all events that reach Joe but shouldn't be detected by him.


If someone has cast a curse on a Physical it may very well also contain an Effect.  For all practical purposes it acst like a normal item (can be moved around and all that), but works like a parasite and is often invisible.  If someone has cast a curse on Joe that turns him into a werewolf every evening, Joe (being a Physical) will contain a WerewolfEffect.  The effect will keep track of the time and when evening comes along it will turn Joe into a werewolf.  See the document on magic and effects for more details.


A Physical may be involved in an Activity.  Furthermore an Activity can have more than one participant (but a Physical cannot be involved in more than one Activity at a time - get the distinction?).  That is the reason why Activity is outside the container hierarchy (it is a subclass of Item, not Physical).  There is no natural place in the container hierarchy for it to reside, since it involves more than one Physical. See the Activity document for more details.


Each Physical may also have a Soul (or several - but that's rare).  The Soul is the one actually controlling the actions of the Physical, the Physical is also known as the soul's body.  To know what actions to execute, however, the Soul must receive events so it knows what's occuring near the Physical.  This is where the Senses comes in.


Let's say Joe is controlled by a player client.  The player client is actually an Account, or a special type of Soul that is controlled by an external player client (ie a real person!).  In order to receive events that reach Joe, the Account needs to become a child of Joe.  However this is not enough - let's say Joe has terrible hearing!  Many of the sounds that reach Joe will not really be heard by Joe.  The solution is that the Account becomes a child of Joe's Senses, instead of Joe himself.  Because the Senses will filter out all events that Joe wouldn't be able to hear.

In some cases, however, souls will want to "cheat".  Imagine a player possessing a sword, so that you can control it.  Even though the sword has no eyes and ears (ie no Senses), the player will want to know what the sword "sees" and "hears".  In that case, the Soul will make itself a child of the sword directly.  It may then "make up" a Senses object that it maintains internally and filters all events through, just to simulate a certain eyesight or hearing range (so that it isn't overwhelmed with events).  But now I'm gonna lay off the details...


An NPCSoul is a Soul that is run by the server, using AI algorithms, behavioural rules, and hip stuff like that.  From the body's point of view (the Physical that the soul is controlling) there's no difference between an NPCSoul and an Account - they are both simply Souls. See the document on Souls and AI for details.


As you can see, Soul, Effect, and Activity all have one thing in common - they implement the Active interface.  Active objects provide an interface for receiving info about the result of an action (ie if the action succeeded or failed).  Soul, Effect, and Activity can all produce actions so they will want to know if their actions succeeded.  See the document on Actions for more details.


ItemHolder is a general representation of a collection of Physicals - a simple container class for nodes that can contain an arbitrary number of anonymous children.  The main difference from Physical is that ItemHolders can contain any type of children (as long as they are Physicals).  Most other subclasses of Physical are made to contain only specific types of children, in specific numbers (for example Physical itself is made to contain 0-n Souls, 0-n Effects, and 0-1 Senses - nothing else).  The property viewer provided by ItemHolder displays the actual contents (as opposed to the properties of the ItemHolder itself, since it hardly has any properties).


ItemHolder has two subclasses: Place and PCStorage.  Place represents a single square in the world, and includes terrain functionality.  So there will be subclasses to Place such as Forest, Desert, Water, etc.  Place implements physical constraints such as checking if an item can fit, or imposing restrictions for certain items - for example damaging items of a certain type that enter.


PCStorage is where your character goes when you are not logged on.  The deal here is that no events will go in or out of the PCStorage and that players within cannot mess around with each other - and stuff like that.  For now there is one global PCStorage, a direct child of the World.  But later on Hotels and things like that will be maintaining their own PCStorages.


There is only one World and it is the top of the container hierarchy, the root node.  It is the only Physical that can survive having a location of null!  It keeps track of the top-level Areas (as children) and contains a PCStorage for characters that are not logged on.  It also keeps an index of all Accounts, regardless of their locations.  Important distinction here - the Accounts are not children of the World - they are children of the bodies they control.  The World needs an index of them, however, for client bootstrapping purposes.


An Area is a matrix (or two-dimensional array) of Places.  It is a unit of geography.  Note that an Area has a location as well, so it may very well be inside a Place which in turn is inside another Area!  Nested Areas are thus possible.  Areas that are not inside another area must be direct children of the World, as mentioned above.

Areas are special in the sense that their children (the Places) are spacially related to each other.  Therefore an Area has the important duty of figuring out how far to propagate an event - it might determine that only a certain subset of the matrix should receive an event because the others are too far away.  This is how the propagation of events is limited.


Finally a Creature is, well, a creature.  Creatures are alive, and can be killed.  They can also hold things - this is represented by the two children that all Creatures have: "worn" and "held".  These are instances of ItemHolder which in turn, of course, can contain other objects.  See the container hierarchy example - it should clearly illustrate this.  The worn/held structure is a good start, but it can be greatly advanced later to include things like where on the body something is worn, how it is held, and stuff like that.


Thing is the superclass of all the "normal" items you would encounter in a tile-based game - things like trees, bags, swords, potatoes, doors, bushes, pools, arrows, cups, stones, walls, books, etc, etc, etc.  I haven't defined this hierarchy yet (only made a small simple one so far for testing purposes), but it will be very large and I will write a seperate document describing it later on.

Henrik Kniberg

Last updated: