Guide: Siege University - 211: Naming Key

== Introduction ==
Dungeon Siege stores all of its resource data internally in one of two databases: the GAS Database and the Content Database. The GAS Database contains the definitions of all of the objects that are used in Dungeon Siege while the Content Database contains the actual data referenced by definitions in the GAS Database. 
The Naming Key provides the link that allows the definitions in the GAS Database to locate items in the Content Database. The idea behind the Naming Key is simple: Every piece of content has a unique Name and given any valid Name you can locate the appropriate content in the Content Database. 
The Naming Key uses index information stored in "NNK" files to associate Names with items in the Content Database. The format used in the NNK files was designed to meet three main goals: the lookup process must be easily automated, the index structure must require minimal maintenance, and all maintenance must be possible using only a simple text editor. As is often the case with a naming system designed to be recognized by a computer, the ease of readability for the rest of us winds up getting tossed out the window. While the Naming Key format may appear to be nothing but gibberish at first glance, rest assured that its Names will start to make sense in very short order.
=== What You Need For This Tutorial ===
*Dungeon Siege 1.1 or later
*Dungeon Siege Tool Kit
*gmax
=== What This Tutorial Assumes You Have Already Learned ===
*Siege U: 100
*Siege U: 200 - Concepts and Terminology
*Siege U: 201 - Templates
=== What This Tutorial Will Teach You ===
*How the Naming Key is read, used, and created
== A Warning ==
The entire Naming Key system relies on correctly formatted and spelled Names. The importance of naming your content properly can't be understated. If a Name is not valid, the Naming Key lookup will fail, files will appear to go missing, tools will not behave as designed, and eventually bugs will get reported that aren't really bugs at all. 
[Examples of common mistakes include using a "_" (underscore) when you should have used a "-" (hyphen) and forgetting to assign a Name to an object in the first place. When something isn't working, check your Names]
== Dissecting A Naming Key "Name" ==
Let's examine some samples of valid Names taken from the Dungeon Siege Content Database:
 m_w_misc_flamethrower
 b_i_glb_placeholder
 t_grs01_houses_guard-stairs
By convention, all Names start with a single character followed by an underscore ("_"). This first character determines the main type of the file that the Name represents. The main type character conveys additional meaning to the Naming Key and describes the information that it contains. Because the type is explicitly encoded in the Name, Names do not require any particular extension (i.e., no .BMP, .PSD, .SNO, nor .ASP). Omitting the extension from the Name allows you to alter the format that the data is stored in (converting a bitmap from a BMP to a PSD, for example) without forcing you to rename all of the instances where the Name has been used.
Once the main type is determined, decrypting a Name is straightforward. Names are parsed left to right, with underscore characters separating successive sections within the Name. Each of the sections is expanded by matching it against sub-type 'trees' defined within the Naming Key NNK files (more on 'trees' a little later). As soon as a matching sub-type tree entry cannot be located for a section, the process stops. The actual location of the file is assembled by concatenating each of the matched sections together and then appending the original Name to the end.
As is the case with filenames in general, all Naming Key Names are considered to be case insensitive. For example, the Name "M_I_GLB" is the same Name as "m_i_glb".
Let's use the Name m_w_misc_flamethrower as an example and determine its location:
We first split the Name into sections to produce:
 m
 w
 misc
 flamethrower
Each section is then matched and expanded to become:
 "Art\Meshes"
 "Weapons"
 "Misc"
(In this example, the "flamethrower" section has no matching sub-type tree.)
Finally, concatenation produces the full location:
 \Art\Meshes\Weapons\Misc\m_w_misc_flamethrower
We can use this same technique to discover the locations of the other two samples listed at the beginning of this section:
 b_i_glb_placeholder
 t_grs01_houses_guard-stairs
generate:
 \Art\Bitmaps\Items\b_i_glb_placeholder
 \Art\Terrain\Grass_1\Houses\t_grs01_houses_guard-stairs
== The Naming Key Layout ==
At this point a key question remains: How is the information needed to match and expand a Name into a Content Database location stored in the NNK files?
Information is stored in the Naming Key in a hierarchical structure, i.e. all the information is arranged in a 'tree' similar to a directory 'tree' on your hard drive.
Adding to the Naming Key is a matter of attaching a new 'tree branch' to an existing branch and giving that new tree branch a Name of its own.
Every tree branch is defined by a line in an NNK file that has the form:
 TREE = <complete branch prefix> , <the branch directory>, "<branch description>"
Here are three sample definitions taken from NNK files that illustrate what an actual tree definition looks like:
TREE = M, 	Meshes,	"Meshes"
TREE = M_I, 	Items, 	"Items"
TREE = M_I_BID,	Biddle,	"Biddle's Item Meshes"
The hierarchical nature of the format makes the order in which the TREE definitions are listed within the NNK files important as subsequent definitions build upon a earlier ones. In the example above, "M_I" must be defined before "M_I_BID" and "M" before "M_I".
Matters get more complicated when you consider in the fact that the Naming Key has support for more than one NNK file at a time. All the NNK files need to be parsed in a known sequence if the order of the TREE definitions spread throughout the NNK files is to be preserved.
NNK files fall into one of two types: "Standard" (created by GPG) and "Extra" (created by the mod community). Ordering NNK files is actually a two-step process: first the Standard NNKs, then the Extra NNKs.
Standard NNK files all have names of the form "NamingKeyXXX" (where the value of XXX in the filename represents the version of the key itself). The Extra NNK files can have any valid Windows filename, as long that name does not start with "NamingKey".
Whenever the Naming Key is loaded, resources directories are scanned and all the standard NNK files are collected and sorted. The Standard NNK with the highest version is the one that gets used. The contents of all other standard keys are ignored.
After the most up-to-date Standard NNK has been located and scanned, ALL other files that end in .NNK are collected, sorted and scanned.
If a Name is encountered more than once, (for example if "M_I_BOB" appears in more than one NNK file) then only the first definition is accepted; any attempt to redefine a Name is ignored.
Creating extra NNK files allows you to extend the content database with your own entries by adding your custom naming keys with names like:
 MyWorkInProgress.NNK
 TeamYahoo_Mod1.NNK
 TeamYahoo_Mod2.NNK
In the long run, keeping the Naming Key definitions separated across multiple NNK files will make it easier for end-users to pick and choose the mod content they want to access and avoid the sort of naming conflicts that arise when two people both define objects that use the same Name.
== Practical Exercise: Extending The Naming Key ==
The following 7-step tutorial will walk you through an example of extending the Naming Key with a new NNK file called "MyStuff.NNK". It illustrates a feature in Siege Max that will let you automatically generate an NNK stub file and place it in the correct directory on your hard drive (so that other programs that use the Naming Key for content lookup can access it)
==== Step 1 ====
Launch Siege Max
==== Step 2 ====
With Siege Max running, open the MAXScript Listener console by selecting it on the main menu
Figure 1 - Launching the Listener
==== Step 3 ====
Enter the Maxscript command dsExtendNamingKey "MyStuff" into the MAXScript Listener console.
Figure 2 - Entering the command (note cursor at end of line) 
==== Step 4 ====
Leave the cursor at the end of the line of text you have typed (as shown in Figure 2 above) and then press the ENTER key on the NUMERIC KEYPAD (not the regular Enter key!). Pressing Numpad-Enter executes the command on the line that the cursor is on. Executing this command will create a new file called MyStuff.NNK (Fig. 3), and then automatically open the new file using "Notepad" to allow you to edit it (Fig. 4). You may want to make a note of the directory on your system in which the new file is created. This is the default location in your "Bits" directory for any extra NNK files.
Figure 3 - Result of dsExtendNamingKey command
Figure 4 - The generated NNK file (before any edits)
==== Step 5 ====
Use the Notepad editor to make a copy the first TREE definition in the generated NNK file and paste it at the end of the file and remove the leading comment (#) marker (Fig. 5).
Adding this definition will allow you to use Names that are prefixed with m_i_bid for any mesh objects that you create. This new "m_i_bid" definition relies upon the fact that the definition for "m_i" already exists (it is defined as part of the Standard NNK file). Remember to save the file after making your changes!
Figure 5 - The generated NNK file (with additional line at bottom)
=== Step 6 ===
Switch back to the Listener console, enter the command dsLoadNamingKey(), then press Numpad-Enter to execute it. This command causes the Naming Key to be reloaded (Fig. 6). Additional information is reported to you regarding the NNK files that are accessed by the loading process. You should see an entry for the EXTRA file "mystuff.nnk" that you just created.
Figure 6 - Loading the Naming Key 
=== Step 7 ===
You can test your new entry to be sure that everything is working properly with another Listener command. Experiment by entering the following commands:
 dsBuildContentLocation "m_i_bid_my-first-model"
returns:
 "Art\Meshes\Items\Biddle\m_i_bid_my-first-model"
and
 dsBuildContentLocation "garbage"
returns:
 "undefined"
because the "garbage" is still not recognized as a valid Name. 
Figure 7 - Testing the new entry 
Once you are satisfied that your new Name has been recognized by the Naming Key you can start to use it to prefix your own content. You are well on your way to organizing content for your own mods!